<?php

namespace Common\Logic;

/**
 * 订单逻辑
 * @modify trainyao 2016-01-05 创建
 */
class OrderLogic extends \Common\Controller\BaseController {

    public $statusMap = array(
            'zh_cn' => array(
                ORDER_BOOKED => '已预订',
                ORDER_PAYED => '已支付',
                ORDER_CHECKINED => '已入住',
                ORDER_CHECKOUTED => '已退房',
                ORDER_CANCELED => '已取消',
                ORDER_OUTDATED => '已过期',
                ORDER_SHOULD_CHECKOUT => '应退房',
            ),
            'en_us' => array(
                ORDER_BOOKED => 'Reserved',
                ORDER_PAYED => 'Paid',
                ORDER_CHECKINED => 'Checkin',
                ORDER_CHECKOUTED => 'Checkout',
                ORDER_CANCELED => 'Cancel',
                ORDER_OUTDATED => 'Outdate',
                ORDER_SHOULD_CHECKOUT => 'Late Checkout',
            ),
            'zh_tw' => array(
                ORDER_BOOKED => '已預訂',
                ORDER_PAYED => '已支付',
                ORDER_CHECKINED => '已入住',
                ORDER_CHECKOUTED => '已退房',
                ORDER_CANCELED => '已取消',
                ORDER_OUTDATED => '已過期',
                ORDER_SHOULD_CHECKOUT => '應退房',
            ),
        );
    public $payChangeTypeMap = array(
            'zh_cn' => array(
                PAY_CHANGE_RECEIPT => '收款',
                PAY_CHANGE_REFUND => '退款',
                PAY_CHANGE_DEPOSIT => '收押金',
                PAY_CHANGE_DEPOSIT_BACK => '退押金',
                PAY_CHANGE_RECEIVABES => '待收款',
            ),
            'en_us' => array(
                PAY_CHANGE_RECEIPT => 'Receipt',
                PAY_CHANGE_REFUND => 'Refunds',
                PAY_CHANGE_DEPOSIT => 'Accept deposits',
                PAY_CHANGE_DEPOSIT_BACK => 'Deposit back',
                PAY_CHANGE_RECEIVABES => 'Receivables',
            ),
            'zh_tw' => array(
                PAY_CHANGE_RECEIPT => '收款',
                PAY_CHANGE_REFUND => '退款',
                PAY_CHANGE_DEPOSIT => '收押金',
                PAY_CHANGE_DEPOSIT_BACK => '退押金',
                PAY_CHANGE_RECEIVABES => '待收款',
            ),
        );

    /**
     * 筛选子订单
     * @modify trainyao 2016-01-08      创建
     * @modify trainyao 2016-06-28 增加房间权限判断
     * @modify wenhui 2017-03-09 是否过滤屏蔽订单电话号码功能isfilter
     * @param  integer   $hotelId        客栈id
     * @param  mixin   $orderIds        父订单id(s)
     * @param  string   $dateStatus     order=预定时间/checkin=入住时间/checkout=退房/within=筛选预定时间在区间内的订单,时间筛选项
     * @param  string   $startDate      时间筛选开始
     * @param  strign   $endDate        时间筛选结束
     * @param  string   $roomId       房间号
     * @param  integer   $status         订单状态
     * @param  integer   $hotelChannelId 客栈渠道id
     * @param  strign   $name           入住人姓名
     * @param  integer   $pageIndex      分页页码
     * @param  integer   $pageSize       每页长度
     * @param  mixin   $withOrderInfo    每条子订单是否包含父订单信息
     * @param  integer   $userloginId    预订者id
     * @param  bool   $isfilter         是否过滤
     * @return array                   结果数组:array('order'=>(父订单信息,可能为空), 'subOrder' => (子订单信息,不为空, name, mobile, identity, user: [{name, mobile, identity},{},...]), 'page' => (分页信息:页码,总页数,每页长度,总条目数))
     */
    public function getSubOrder($hotelId, $orderIds = null, $dateStatus = null, $startDate = null, $endDate = null, $roomId = null, $status = null, $hotelChannelId = null, $name = null, $pageIndex = null, $pageSize = null, $withOrderInfo = false, $userloginId = null, $isfilter = true, $version = null) {
        $orderRoom = null;
        $orderInfo = array();
        $orderRoomModel = D('OrderRoom');
        // 搜预定人姓名,来源 时先搜父订单
        // 搜房间号先搜房间再搜相关子订单
        if (!empty($orderIds)) {
            $orderRoom = $orderRoomModel->getInfoByOrder($orderIds, false);
        } else if (!empty($userloginId)) {
            // 根据预定人用户ID
            $orderInfoModel = D('OrderInfo');
            $orderInfo = $orderInfoModel->getInfoByUser($userloginId);

            if (!empty($orderInfo)) {
                $orderInfoIds = array_column($orderInfo, 'id');
                $orderRoom = $orderRoomModel->getInfoByOrder($orderInfoIds, false);
            } else {
                $orderRoom = array();
            }
        }
        // 其他情况,先根据客栈搜子订单
        if (is_null($orderRoom)) {
            $orderRoom = $orderRoomModel->getInfoByHotelRoom($hotelId);
        }

        // 读取redis,将有效已过期订单变为已预订
        if (!empty($orderRoom)) {
            $hotelIds = array_unique(array_column($orderRoom, 'hotelentity_id'));

            // 统计过期子订单ID,获取redis订单,将有效已过期订单转为已预订
            $outDateOrderRoomIds = array();
            foreach ($orderRoom as $orderRoomItem) {
                if ($orderRoomItem['status'] == ORDER_OUTDATED) {
                    array_push($outDateOrderRoomIds, $orderRoomItem['id']);
                }
            }
            unset($orderRoomItem);
            if (!empty($outDateOrderRoomIds)) {
                $orderRoom = getArrayValueAsIndex($orderRoom, 'id');
                $orderRoomModel = D('OrderRoom');
                $redisOrderRecordInfo = $orderRoomModel->getInfoInRedisByHotelRoomOrderRoom($hotelIds, null, $outDateOrderRoomIds);
                if ($redisOrderRecordInfo === false) {
                    // redis查询失败
                    throw new \Exception('500,506', 506);
                }
                foreach ($redisOrderRecordInfo as $redisOrderRecordItem) {
                    $orderRoom[$redisOrderRecordItem['orderroom_id']]['status'] = ORDER_BOOKED;
                }
                unset($redisOrderRecordItem);
                $orderRoom = array_values($orderRoom);
            }
        }
        // 补充子订单入住人信息
        $orderRoom = $this->fillOrderUserInfo($hotelId, $orderRoom);

        // 根据房间id筛选
        if (!empty($roomId)) {
            foreach ($orderRoom as $index => $orderRoomItem) {
                if ($orderRoomItem['roominfo_id'] != $roomId) {
                    unset($orderRoom[$index]);
                }
            }
            unset($orderRoomItem);
        }

        // 入住时间,退房时间,预定时间,状态 筛选
        if (!empty($dateStatus) && !empty($startDate) && !empty($endDate) && !empty($orderRoom)) {
            switch ($dateStatus) {
                case 'order':
                    foreach ($orderRoom as $index => $orderRoomItem) {
                        if (!isBetweenTime($orderRoomItem['createtime'], $startDate, $endDate . " 23:59:59")) {
                            unset($orderRoom[$index]);
                        }
                    }
                    unset($orderRoomItem);
                    break;
                case 'checkin':
                    foreach ($orderRoom as $index => $orderRoomItem) {
                        if (!isBetweenTime($orderRoomItem['startdate'], $startDate, $endDate)) {
                            unset($orderRoom[$index]);
                        }
                    }
                    unset($orderRoomItem);
                    break;
                case 'checkout':
                    foreach ($orderRoom as $index => $orderRoomItem) {
                        // TODO:需要确认是否筛选enddate,还是checkoutdate
                        if (!isBetweenTime($orderRoomItem['checkoutdate'], $startDate, $endDate)) {
                            unset($orderRoom[$index]);
                        }
                    }
                    unset($orderRoomItem);
                    break;
                case 'within':
                    foreach ($orderRoom as $index => $orderRoomItem) {
//                        $startDateIn = isBetweenTime($orderRoomItem['startdate'], $startDate, $endDate);
//                        $endDateIn = isBetweenTime($orderRoomItem['checkoutdate'], $startDate, $endDate);
//
//                        // 不在时间区间内
//                        if ((!$startDateIn && !$endDateIn)) {
//                            unset($orderRoom[$index]);
//                        }

                        $startOutDate = strtotime($orderRoomItem['checkoutdate']) < strtotime($startDate);
                        $endOutDate = strtotime($orderRoomItem['startdate']) > strtotime($endDate);
                        if ($startOutDate || $endOutDate) {
                            unset($orderRoom[$index]);
                        }
                    }
                    unset($orderRoomItem);
                    break;
            }
        }
        if (!is_null($status) && !empty($orderRoom)) {
            foreach ($orderRoom as $index => $orderRoomItem) {
                if ($orderRoomItem['status'] != $status) {
                    unset($orderRoom[$index]);
                }
            }
            unset($orderRoomItem);
        }
        // 补充父订单信息(有部分筛选情况已查询出orderInfo,在这里传入进行数据格式化)
        if ((!empty($withOrderInfo) || !empty($hotelChannelId)) && !empty($orderRoom)) {
            $orderRoom = $this->fillOrderInfo($hotelId, $orderRoom, $orderInfo);
            if (!empty($hotelChannelId)) {
                foreach ($orderRoom as $index => &$orderRoomItem) {
                    if ($orderRoomItem['order']['hotelchannel_id'] != $hotelChannelId) {
                        unset($orderRoom[$index]);
                        continue;
                    }
                    // 去除父订单信息
                    if (empty($withOrderInfo)) {
                        unset($orderRoomItem['order']);
                    }
                }
                unset($orderRoomItem);
            }
        }
        // 修改该退房而未退房的子订单状态  status = 6
        if (!is_null($version)) {
            if ($version >= '2.0.17') {
                if (!empty($orderRoom)) {
                    $orderRoom = $this->modifyOrderRoomStatus($orderRoom);
                }
            }
        } else {
            if (!empty($orderRoom)) {
                $orderRoom = array_values($orderRoom);
                $orderRoom = $this->modifyOrderRoomStatus($orderRoom);
            }
        }

        //过滤入住人信息
        if ($name) {
            $orderRoom = $this->filterSearch($orderRoom, $name);
        }
        if (MODULE_NAME != 'Extend') {
            // 判断是否有权限查看信息(预定端查看不需检查查看权限)
            $canSeeMobile = true;
            $adminAuthorityLogic = A('Common/AdminAuthority', 'Logic');
            $canSeeMobile = $adminAuthorityLogic->check($hotelId, null, AUTHORITY_CONTACT_INFO_BLOCK);
            if (!$canSeeMobile && $isfilter) {
                foreach ($orderRoom as &$orderRoomItem) {
                    $orderRoomItem['mobile'] = !empty($orderRoomItem['mobile']) ? substr($orderRoomItem['mobile'], 0, 3) . '********' : $orderRoomItem['mobile'];
                    $orderRoomItem['order']['mobile'] = !empty($orderRoomItem['order']['mobile']) ? substr($orderRoomItem['order']['mobile'], 0, 3) . '********' : $orderRoomItem['order']['mobile'];
                }
                unset($orderRoomItem);
            }
            
            // 根据房间权限去除无权限的数据
            $adminId = getUserId();
            $adminAuthorityLogic = A('Common/AdminAuthority', 'Logic');
            if (!$adminAuthorityLogic->checkIsAdmin($adminId, $hotelId)) {
                $accountLogic = A('Common/Account', 'Logic');
                $roomAuthority = $accountLogic->getAdminRoomAuthority($adminId, $hotelId);
                foreach ($orderRoom as $index => $orderRoomItem) {
                    if (!in_array($orderRoomItem['roominfo_id'], $roomAuthority)) {
                        unset($orderRoom[$index]);
                    }
                }
                unset($orderRoomItem);
            }
        }
        $orderRoom = array_values($orderRoom);

        // 补充房间查房状态 0=未查(查房中) 1=已查 2=知道了  3=未开启查房按钮 4=未发起查房任务
        if (!empty($orderRoom)) {
            $enableCheckRoom = $this->hotelCheckRoomSwitch($hotelId);
            $hotelRoomCheckModel = D('HotelRoomCheck');
            foreach ($orderRoom as $index => &$orderRoomItem) {
                $checkRoomdata = $hotelRoomCheckModel->getInfoBySubOrderId($orderRoomItem['id']);
                $orderRoomItem['checkRoom'] = !empty($checkRoomdata) ? $checkRoomdata['type'] : 4;
                $orderRoomItem['checkRoom'] = $enableCheckRoom ? $orderRoomItem['checkRoom'] : 3;
            }
            unset($orderRoomItem);
        }

        // 生成分页信息
        $orderRoom = $this->generatePageInfo($orderRoom, $pageIndex, $pageSize);

        // 判断房间是否已经删除
        $orderRoom = $this->fillRoomDeleted($hotelId, $orderRoom);

        return $orderRoom;
    }

    /**
     * @add Paddy 2016-11-21 获取查询订单列表 （For Mobile）
     * @modify wenhui 2017-02-09 添加查询字段 type statusType startTime endTime
     * @add zhangzhen 2017-3-7   子管理权限（For Mobile）
     * @param integer $hotelId 客栈id
     * @param string $keywords 关键词，模糊匹配入住人、手机号、房间号
     * @param integer $pageIndex 页码
     * @param integer $pageSize 每页大小
     * @param integer $type 指定条件搜索，1：按入住人名称、2：手机、3：房间号
     * @param integer $statusType 按订单状态搜索，0：已预定、1：已支付、2：已入住、3：已退房、4：已取消、5：已过期 默认全部状态
     * @param integer $startTime 搜索开始时间 格式时间戳 1479980027
     * @param integer $endTime 搜索结束时间 格式时间戳 1479980027
     * @return array  结果数组:array('order'=>(父订单信息,可能为空), 'subOrder' => (子订单信息,不为空, name, mobile, identity, user: [{name, mobile, identity},{},...]), 'page' => (分页信息:页码,总页数,每页长度,总条目数))
     */
    public function searchByKeywords($hotelId, $keywords = null, $pageIndex = null, $pageSize = null, $type = null, $statusType = null, $startTime = null, $endTime = null) {
        $orderRoom = null;
        $orderRoomModel = D('OrderRoom');
        // 先根据客栈搜子订单
        $orderRoom = $orderRoomModel->getInfoByHotelRoom($hotelId);
        $userId = getUserId();
        $adminHotelModel = D('AdminHotel');
        $adminHotelInfo = $adminHotelModel->getInfoByAdminHotel($userId, $hotelId);
        if($adminHotelInfo['role'] !== '1'){
            $hotelRoomAuthorityModel= D('HotelRoomAuthority');
            $hotelRoomAuthorityInfos = $hotelRoomAuthorityModel ->getInfoByAdminHotel($userId, $hotelId);
            $adminRoomIds = array_column($hotelRoomAuthorityInfos,'roominfo_id');
        }
        // 读取redis,将有效已过期订单变为已预订
        if (!empty($orderRoom)) {
            $hotelIds = array_unique(array_column($orderRoom, 'hotelentity_id'));
    
            // 统计过期子订单ID,获取redis订单,将有效已过期订单转为已预订
            $outDateOrderRoomIds = array();
            foreach ($orderRoom as $key => $orderRoomItem) {

                if(isset($adminRoomIds) && !in_array($orderRoomItem['roominfo_id'], $adminRoomIds)){
                    unset($orderRoom[$key]);
                    continue;
                }
                if ($orderRoomItem['status'] == ORDER_OUTDATED) {
                    array_push($outDateOrderRoomIds, $orderRoomItem['id']);
                }
            }
                    
            unset($orderRoomItem);
            if (!empty($outDateOrderRoomIds)) {
                $orderRoom = getArrayValueAsIndex($orderRoom, 'id');
                $orderRoomModel = D('OrderRoom');
                $redisOrderRecordInfo = $orderRoomModel->getInfoInRedisByHotelRoomOrderRoom($hotelIds, null, $outDateOrderRoomIds);
                if ($redisOrderRecordInfo === false) {
                    // redis查询失败
                    throw new \Exception('500,506', 506);
                }
                foreach ($redisOrderRecordInfo as $redisOrderRecordItem) {
                    $orderRoom[$redisOrderRecordItem['orderroom_id']]['status'] = ORDER_BOOKED;
                }
                unset($redisOrderRecordItem);
                $orderRoom = array_values($orderRoom);
            }
        }
    
        // 补充子订单入住人信息
        $orderRoom = $this->fillOrderUserInfo($hotelId, $orderRoom);

        // v2.0.05搜索条件的细分
        $version = getVersion(array('2.0.17', '2.0.05', '2.0.02', '2.0.01'));
        if ($version >= '2.0.05' && !is_null($type)) {
            // 按条件筛选
            switch ($type) {
                case 1:
                    $orderRoom = $this->searchOption($orderRoom, $keywords, 'name', $startTime, $endTime, $statusType);
                    break;
                case 2:
                    $orderRoom = $this->searchOption($orderRoom, $keywords, 'mobile', $startTime, $endTime, $statusType);
                    break;
                case 3:
                    $orderRoom = $this->searchOption($orderRoom, $keywords, 'roominfo_name', $startTime, $endTime, $statusType);
                    break;
            }
        } else {
            // 筛选
            if (!empty($keywords)) {
                foreach ($orderRoom as $index => $orderRoomItem) {
                    if ((strpos($orderRoomItem['name'], $keywords) === false)&&(strpos($orderRoomItem['mobile'], $keywords) === false)&&(strpos($orderRoomItem['roominfo_name'], $keywords) === false)) {
                        unset($orderRoom[$index]);
                    }
                }
                unset($orderRoomItem);
            }
        }

        $orderRoom = array_values($orderRoom);
        // 修改该退房而未退房的子订单状态  status = 6
        if ($version >= '2.0.17') {
            if (!empty($orderRoom)) {
                $orderRoom = $this->modifyOrderRoomStatus($orderRoom);
            }
        } else {
            if (!empty($orderRoom)) {
                $orderRoom = $this->modifyOrderRoomStatus($orderRoom);
            }
        }

        // 补充父订单信息(有部分筛选情况已查询出orderInfo,在这里传入进行数据格式化)
        if ( !empty($orderRoom)) {
            $orderRoom = $this->fillOrderInfo($hotelId, $orderRoom, null);
        }

        // 生成分页信息
        $orderRoom = $this->generatePageInfo($orderRoom, $pageIndex, $pageSize);
    
        // 判断房间是否已经删除
        $orderRoom = $this->fillRoomDeleted($hotelId, $orderRoom);
    
        return $orderRoom;
    }

    /**
     * 订单筛选条件函数
     * @modify wenhui 2017-02-10 创建
     * @param  array   $orderRoom 订单数据数组
     * @param  string   $keywords 搜索关键词
     * @param  int   $type 搜索类型
     * @param  string   $startTime 开始时间
     * @param  string   $endTime 结束时间
     * @param  string   $statusType 订单状态
     */
    private function searchOption($orderRoom, $keywords, $type, $startTime, $endTime, $statusType) {
       if (!empty($keywords)) {
            // 根据keywords筛选
            foreach ($orderRoom as $index => $orderRoomItem) {
                if ((strpos($orderRoomItem[$type], $keywords) === false)) {
                    unset($orderRoom[$index]);
                }
            }
            unset($orderRoomItem);
            // 根据时间，状态筛选 statusType = null 就不筛选
            if (is_null($statusType)) {
                foreach ($orderRoom as $index => $orderRoomItem) {
                    if (strtotime($orderRoomItem['createtime']) < $startTime || strtotime($orderRoomItem['createtime']) > $endTime) {
                        unset($orderRoom[$index]);
                    }
                }
                unset($orderRoomItem);
            } else {
                foreach ($orderRoom as $index => $orderRoomItem) {
                    if ((strtotime($orderRoomItem['createtime']) < $startTime || strtotime($orderRoomItem['createtime']) > $endTime) || $orderRoomItem['status'] != $statusType) {
                        unset($orderRoom[$index]);
                    }
                }
                unset($orderRoomItem);
            }
        } else {
            // keywords为空时根据时间，状态筛选 statusType = null 就不筛选
            if (is_null($statusType)) {
                foreach ($orderRoom as $index => $orderRoomItem) {
                    if (strtotime($orderRoomItem['createtime']) < $startTime || strtotime($orderRoomItem['createtime']) > $endTime) {
                        unset($orderRoom[$index]);
                    }
                }
                unset($orderRoomItem);
            } else {
                foreach ($orderRoom as $index => $orderRoomItem) {
                    if ((strtotime($orderRoomItem['createtime']) < $startTime || strtotime($orderRoomItem['createtime']) > $endTime) || $orderRoomItem['status'] != $statusType) {
                        unset($orderRoom[$index]);
                    }
                }
                unset($orderRoomItem);
            }
        }

        return $orderRoom;
    }
    
    /**
     * 生成分页信息
     * @modify trainyao 2016-01-08 创建
     * @param  array   $orderRoom 子订单信息
     * @param  integer   $pageIndex 页码
     * @param  integer   $pageSize  每页大小
     * @return array              array('subOrder' => (子订单信息,不为空), 'page' => (分页信息:页码,总页数,每页长度,总条目数))
     */
    private function generatePageInfo($orderRoom, $pageIndex, $pageSize) {
        if (empty($pageIndex) || empty($pageSize)) {
            return array('subOrder' => $orderRoom);
        }

        // 处理分页
        $pageInfo = array();
        $orderRoom = createPageInfo($orderRoom, $pageIndex, $pageSize);
        $pageInfo = array(
            'current' => $orderRoom['current'],
            'size' => $orderRoom['size'],
            'total' => $orderRoom['total'],
            'pageTotal' => $orderRoom['pageTotal'],
        );
        $orderRoom = $orderRoom['data'];

        return array('subOrder' => $orderRoom, 'page' => $pageInfo);
    }

    /**
     * 判断订单房间是否已经删除,补充标识
     * @modify trainyao 2016-04-25 创建
     * @param  integer   $hotelId   客栈id
     * @param  array   $orderRoom array('subOrder' => array(array(
     *                            ), array()...),
     *                                  'page' => 分页信息)
     * @return array              返回补充标识后的$orderRoom
     */
    private function fillRoomDeleted($hotelId, $orderRoom) {
        // 房型和房间号
        $roomTypeLogic = A('Common/RoomType', 'Logic');
        $roomTypeInfo = $roomTypeLogic->getInfoByHotel($hotelId);
        $notDeleteRoomIds = array();
        foreach ($roomTypeInfo as $roomTypeItem) {
            $notDeleteRoomIds = array_merge($notDeleteRoomIds, array_column($roomTypeItem['room'], 'id'));
        }
        unset($roomTypeItem);
        
        // 遍历数组,补充标识
        foreach ($orderRoom['subOrder'] as &$orderRoomItem) {
            if (!in_array($orderRoomItem['roominfo_id'], $notDeleteRoomIds)) {
                $orderRoomItem['roomInfoDelete'] = IS_DELETE;
            } else {
                $orderRoomItem['roomInfoDelete'] = NOT_DELETE;
            }
        }
        unset($orderRoomItem);

        return $orderRoom;
    }

    /**
     * 获取客栈订单信息,以父订单为单位
     * 方法会抛异常
     * @modify trainyao 2016-01-05 创建
     * @modify AmosZhong 2016-08-08 查询是否可以重发短信
     * @modify wenhui 2017-03-02 添加订单支付记录
     * @modify wenhui 2017-03-09 是否过滤屏蔽订单电话号码功能isfilter
     * @param  integer   $hotelId   客栈id
     * @param  array   $orderIds   订单id
     * @param  mixin   $withUsers   是否取订单入住人
     * @param  boll   $isfilter   是否过滤
     * @param  string   $version   移动端版本
     * @return array                订单数据[{id, hotelentity_id, hotelchannel_id, payment, mobile, name, deposit, receipt, userlogin_id, identity, remark, 
     *                                         rooms=> [{id, hotelentity_id, orderinfo_id, roominfo_id, status, payment, startdate, enddate, checkoutdate, roomtype_name, roominfo_name, creator,
     *                                                   createtime, night, realnight, name, mobile, identity, roomInfoDelete, 
     *                                             user=> [{userlogin_id, userroom_id, orderuser_id, name, mobile, identity, printcount, startdate, enddate, isdelete
     *                                                     }, {}, {},...],
     *                                                  }, {}, {},....],
     *                                       }, {}, {},...]
     */
    public function getOrderInfo($hotelId, $orderIds = null, $withUsers = true, $isfilter = true, $version = null) {
        // 收集父订单信息
        $orderInfoModel = D('OrderInfo');
        $orderInfo = array();
        if (!empty($orderIds)) {
            $orderInfo = $orderInfoModel->getInfo($orderIds, false);
            if (empty($orderInfo)) {
                throw new \Exception('403,202', 202);
                return array();
            }
            if (count($orderIds) == 1) {
                $orderInfo = array($orderInfo);
            }
            // 检查可操作性
            foreach ($orderInfo as $order) {
                if ($order['hotelentity_id'] != $hotelId) {
                    throw new \Exception('403,202', 202);
                }
            }
            unset($order);
        } else {
            $orderInfo = $orderInfoModel->getInfoByHotel($hotelId);
            $orderIds = array_column($orderInfo, 'id');
        }

        // 收集子订单信息
        $orderRoom = $this->getSubOrder($hotelId, $orderIds, null, null, null, null, null, null, null, null, null, null, null, $isfilter, $version);
        $orderRoom = $orderRoom['subOrder'];
        $orderRoomIds = array_column($orderRoom, 'id');
        // 统计过期子订单ID,获取redis订单,将有效已过期订单转为已预订
        $outDateOrderRoomIds = array();
        foreach ($orderRoom as $orderRoomItem) {
            if ($orderRoomItem['status'] == ORDER_OUTDATED) {
                array_push($outDateOrderRoomIds, $orderRoomItem['id']);
            }
        }
        unset($orderRoomItem);
        if (!empty($outDateOrderRoomIds)) {
            $orderRoom = getArrayValueAsIndex($orderRoom, 'id');
            $orderRoomModel = D('OrderRoom');
            $redisOrderRecordInfo = $orderRoomModel->getInfoInRedisByHotelRoomOrderRoom($hotelId, null, $outDateOrderRoomIds);
            if ($redisOrderRecordInfo === false) {
                // redis查询失败
                throw new \Exception('500,506', 506);
            }
            foreach ($redisOrderRecordInfo as $redisOrderRecordItem) {
                $orderRoom[$redisOrderRecordItem['orderroom_id']]['status'] = ORDER_BOOKED;
            }
            unset($redisOrderRecordItem);
            $orderRoom = array_values($orderRoom);
        }

        // 处理订单入住人信息
        if ($withUsers === true) {
            $userRoomModel = D('UserRoom');
            $userRoomInfo = $userRoomModel->getInfosByOrderRoom($orderRoomIds);
            $userRoomInfo = getArrayValueAsIndex($userRoomInfo, 'orderroom_id', 'multi');

            // 取出入住人信息
            $orderUserModel = D('OrderUser');
            $orderUsers = $orderUserModel->getInfoByOrder($orderIds);
            $orderUsers = getArrayValueAsIndex($orderUsers, 'id');

            foreach ($orderRoom as &$orderRoomItem) {
                $orderRoomItem['user'] = array();
                $userRoomInfoItem = $userRoomInfo[$orderRoomItem['id']];
                if (!empty($userRoomInfoItem)) {
                    foreach ($userRoomInfoItem as $item) {
                        array_push($orderRoomItem['user'], array(
                            'userroom_id' => $item['id'],
                            'orderuser_id' => $item['orderuser_id'],
                            'userlogin_id' => $item['userlogin_id'],
                            'areacode' => $orderUsers[$item['orderuser_id']]['areacode'],
                            'name' => $orderUsers[$item['orderuser_id']]['name'],
                            'mobile' => $orderUsers[$item['orderuser_id']]['mobile'],
                            'identity' => $orderUsers[$item['orderuser_id']]['identity'],
                            'idsex' => $orderUsers[$item['orderuser_id']]['idsex'],
                            'idnation' => $orderUsers[$item['orderuser_id']]['idnation'],
                            'idaddress' => $orderUsers[$item['orderuser_id']]['idaddress'],
                            'printcount' => $item['printcount'],
                            'rfcount' => $item['rfcount'],
                            'startdate' => $item['startdate'],
                            'enddate' => $item['enddate'],
                            'isdelete' => $orderUsers[$item['orderuser_id']]['isdelete'],
                        ));
                    }
                    unset($item);
                }
            }
            unset($orderRoomItem);
        }

        // 处理子订单数据
        $orderRoom = getArrayValueAsIndex($orderRoom, 'orderinfo_id', 'multi');
        $roomInfoModel = D('RoomInfo');
        foreach ($orderInfo as &$order) {
            $order['rooms'] = $orderRoom[$order['id']];
        }
        unset($order);

        // 处理分销渠道数据
        $orderInfo = $this->fillChannelInfo($hotelId, $orderInfo);

        // 判断是否有权限查看信息
        $canSeeMobile = true;
        $canSeeID = true;
        if (MODULE_NAME != 'Extend') {
            $adminAuthorityLogic = A('Common/AdminAuthority', 'Logic');
            $canSeeMobile = $adminAuthorityLogic->check($hotelId, null, AUTHORITY_CONTACT_INFO_BLOCK);
            $canSeeID = $adminAuthorityLogic->check($hotelId, null, AUTHORITY_ID_INFO_BLOCK);
        }
        if (!$canSeeMobile && $isfilter) {
            foreach ($orderInfo as &$orderInfoItem) {
                $orderInfoItem['trueMobile'] = $orderInfoItem['mobile'];
                $orderInfoItem['mobile'] = !empty($orderInfoItem['mobile']) ? substr($orderInfoItem['mobile'], 0, 3) . '********' : $orderInfoItem['mobile'];
                foreach ($orderInfoItem['rooms'] as &$orderRoomItem) {
                    $orderRoomItem['mobile'] = !empty($orderRoomItem['mobile']) ? substr($orderRoomItem['mobile'], 0, 3) . '********' : $orderRoomItem['mobile'];
                    foreach ($orderRoomItem['user'] as &$orderUserItem) {
                        $orderUserItem['mobile'] = !empty($orderUserItem['mobile']) ? substr($orderUserItem['mobile'], 0, 3) . '********' : $orderUserItem['mobile'];
                    }
                    unset($orderUserItem);
                }
                unset($orderRoomItem);
            }
            unset($orderInfoItem);
        }

        //检查是否为客栈管理员
        $adminHotelModel = D('AdminHotel');
        $userId = getUserId();
        $adminHotel = $adminHotelModel->getInfoByAdminHotel($userId, $hotelId);
        //不是客栈创建人员，需要检查操作权限
        $isAdmin = true;
        if ($adminHotel['role'] != HOTEL_ROLE_OWNER) {
            $isAdmin = false;
        }
        if ($canSeeID && !$isAdmin && $isfilter) {
            foreach ($orderInfo as &$orderInfoItem) {
                foreach ($orderInfoItem['rooms'] as &$orderRoomItem) {
                    foreach ($orderRoomItem['user'] as &$orderUserItem) {
                        $orderUserItem['identity'] = !empty($orderUserItem['identity']) ? substr($orderUserItem['identity'], 0, 4) . '****' . substr($orderUserItem['identity'], mb_strlen($orderUserItem['identity'])-4) : $orderUserItem['identity'];
                        $orderUserItem['idaddress'] = !empty($orderUserItem['idaddress']) ? mb_substr($orderUserItem['idaddress'], 0, 4) . '****' . mb_substr($orderUserItem['idaddress'], mb_strlen($orderUserItem['idaddress'])-4) : $orderUserItem['idaddress'];
                    }
                    unset($orderUserItem);
                }
                unset($orderRoomItem);
            }
            unset($orderInfoItem);
        }

        // 是否开启会员立减优惠
        // 获取客栈所有房型
        $roomTypLogic = A('Common/RoomType', 'Logic');
        $roomTypInfo = $roomTypLogic->getInfoByHotel($hotelId);
        $minusTypes = array_column($roomTypInfo, 'minustype');
        rsort($minusTypes, SORT_NUMERIC);

        $hotelDetail = D('HotelDetail')->getInfoByHotel($hotelId);
        // 是否有立减优惠
        $minusenable = $minusTypes[0] == 0 ? 0 : $hotelDetail['minusenable'];
        $orderInfo[0]['minusEnable'] = $minusenable;

        // 是否有优惠券
        if (!is_null($orderIds) && count($orderIds) == 1) {
            $userCouponModel = D('UserCoupon');
            $userCouponInfo = $userCouponModel->getUserCouponByOrderId($orderIds[0]);
            if (!empty($userCouponInfo)) {
                $hotelCouponModel = D('HotelCoupon');
                $hotelCouponInfo = $hotelCouponModel->getCouponByIds($userCouponInfo['coupon_id']);
                $orderInfo[0]['couponGetNo'] = $userCouponInfo['no'];
                $orderInfo[0]['couponType'] = $hotelCouponInfo[0]['type'];
                $orderInfo[0]['couponpPrice'] = $hotelCouponInfo[0]['price'];
                if ($hotelCouponInfo[0]['type'] == 1) {
                    $orderInfo[0]['couponRule'] = $hotelCouponInfo[0]['minus_price'];
                } else if ($hotelCouponInfo[0]['type'] == 2) {
                    $orderInfo[0]['couponRule'] = $hotelCouponInfo[0]['discount'];
                } else {
                    $orderInfo[0]['couponRule'] = 0;
                }
            } else {
                $orderInfo[0]['userGetNo'] = '';
                $orderInfo[0]['couponType'] = '0';
                $orderInfo[0]['couponpPrice'] = '0';
                $orderInfo[0]['couponRule'] = '0';
            }
        }

        // 获取订单支付记录
        if (!is_null($orderIds) && count($orderIds) == 1) {
            if (is_array($orderIds)) {
                $orderId = implode(',', $orderIds);
            } else {
                $orderId = $orderIds;
            }

            $orderRecordModel = D('OrderRecord');
            $orderRecordInfos = $orderRecordModel->getInfoByOrder($orderId);
            $orderRecordIds = array_column($orderRecordInfos, 'id'); 
            $payHistoryInfo = $this->getPayHistoryData($hotelId, $orderRecordIds, true);
            $payHistoryArray = array(
                'receivedInfo' => array(),
                'refundInfo' => array(),
                'otherReceivedInfo' => array(),
            );
            // 计算已退金额 已退押金
            $orderInfo[0]['refundPrice'] = '';
            $orderInfo[0]['refundDeposit'] = '';
            // 计算其他消费 已收 未收金额
            $orderInfo[0]['otherReceivePrice'] = 0;
            $orderInfo[0]['otherUncollectePrice'] = 0;

            // 货币资源
            $currencyLogic = A('Common/Currency', 'Logic');
            $currencyData = $currencyLogic->getBpCurrency();
            $currencyData = getArrayValueAsIndex($currencyData,'id');
            // 0:收款 1：押金 2：退款 3：退押金
            if (!empty($payHistoryInfo)) {
                foreach ($payHistoryInfo as $key => $payHistoryItem) {
                    switch ($payHistoryItem['type']) {
                        case 0:
                            $receiptArrays = array(
                                'pay' => $payHistoryItem['pay'],
                                'type' => $payHistoryItem['type'],
                                'name' => $payHistoryItem['name'],
                                'id' => $payHistoryItem['id'],
                                'hotelPayId' => $payHistoryItem['hotelpay_id'],
                                'transBeforePay' => $payHistoryItem['trans_before_pay'],
                                'currencyId' => $payHistoryItem['currency_id'],
                                'currencyName' => $currencyData[$payHistoryItem['currency_id']]['name'],
                            );
                            array_push($payHistoryArray['receivedInfo'], $receiptArrays);
                            break;
                        case 1:
                            $receiptArrays = array(
                                'pay' => $payHistoryItem['pay'],
                                'type' => $payHistoryItem['type'],
                                'name' => $payHistoryItem['name'],
                                'id' => $payHistoryItem['id'],
                                'hotelPayId' => $payHistoryItem['hotelpay_id'],
                                'transBeforePay' => $payHistoryItem['trans_before_pay'],
                                'currencyId' => $payHistoryItem['currency_id'],
                                'currencyName' => $currencyData[$payHistoryItem['currency_id']]['name'],
                            );
                            array_push($payHistoryArray['receivedInfo'], $receiptArrays);
                            break;
                        case 2:
                            $refundArrays = array(
                                'pay' => $payHistoryItem['pay'],
                                'type' => $payHistoryItem['type'],
                                'name' => $payHistoryItem['name'],
                                'id' => $payHistoryItem['id'],
                                'hotelPayId' => $payHistoryItem['hotelpay_id'],
                                'transBeforePay' => $payHistoryItem['trans_before_pay'],
                                'currencyId' => $payHistoryItem['currency_id'],
                                'currencyName' => $currencyData[$payHistoryItem['currency_id']]['name'],
                            );
                            array_push($payHistoryArray['refundInfo'], $refundArrays);

                            $orderInfo[0]['refundPrice'] += $payHistoryItem['pay'];
                            break;
                        case 3:
                            $refundArrays = array(
                                'pay' => $payHistoryItem['pay'],
                                'type' => $payHistoryItem['type'],
                                'name' => $payHistoryItem['name'],
                                'id' => $payHistoryItem['id'],
                                'hotelPayId' => $payHistoryItem['hotelpay_id'],
                                'transBeforePay' => $payHistoryItem['trans_before_pay'],
                                'currencyId' => $payHistoryItem['currency_id'],
                                'currencyName' => $currencyData[$payHistoryItem['currency_id']]['name'],
                            );
                            array_push($payHistoryArray['refundInfo'], $refundArrays);

                            $orderInfo[0]['refundDeposit'] += $payHistoryItem['pay'];
                            break;
                        default :
                            if ($payHistoryItem['hotelpay_id'] != 0) {
                                // 他消费已收金额
                                $orderInfo[0]['otherReceivePrice'] += $payHistoryItem['pay'];
                            } else {
                                // 他消费未收金额
                                $orderInfo[0]['otherUncollectePrice'] += $payHistoryItem['pay'];
                            }

                            $otherArrays = array(
                                'pay' => $payHistoryItem['pay'],
                                'type' => $payHistoryItem['type'],
                                'name' => $payHistoryItem['name'],
                                'id' => $payHistoryItem['id'],
                                'hotelPayId' => $payHistoryItem['hotelpay_id'],
                                'otherCostName' => $payHistoryItem['otherCostName'],
                                'transBeforePay' => $payHistoryItem['trans_before_pay'],
                                'currencyId' => $payHistoryItem['currency_id'],
                                'currencyName' => $currencyData[$payHistoryItem['currency_id']]['name'],
                            );
                            array_push($payHistoryArray['otherReceivedInfo'], $otherArrays);

                            break;
                    }
                }
                unset($payHistoryItem);
            }

            $orderInfo[0]['payHistory'] = $payHistoryArray;

        }

        return $orderInfo;
    }

    /**
     * 获取订单支付历史
     * @modify trainyao 2016-01-14 创建
     * @param  integer   $hotelId   客栈id
     * @param  integer   $orderId   父订单id
     * @param  boolean  $withBack  是否包含退款退押金信息
     * @return array              支付历史
     */
    public function getPayHistory($hotelId, $orderId, $withBack = false) {
        $orderRecordModel = D('OrderRecord');
        $orderRecordInfos = $orderRecordModel->getInfoByOrder($orderId);
        if (empty($orderRecordInfos)) {
            return array();
        }
        $orderRecordIds = array_column($orderRecordInfos, 'id');

        return $this->getPayHistoryData($hotelId, $orderRecordIds, $withBack);
    }

    /**
     * 抽离获取支付历史逻辑供[查看订单历史][查看支付历史]接口使用
     * @modify trainyao 2016-01-14      创建
     * @param  integer   $hotelId       客栈id
     * @param  array   $orderRecordIds 订单记录ids
     * @param  boolean  $withBack       是否包含退款退押金信息
     * @return array                   支付历史数据
     */
    public function getPayHistoryData($hotelId, $orderRecordIds, $withBack = false) {
        /*$type = null;
        if ($withBack === false) {
            $type = array(PAY_CHANGE_RECEIPT, PAY_CHANGE_DEPOSIT);
        }*/
        $orderPayRecordModel = D('OrderPayRecord');
        $orderPayRecords = $orderPayRecordModel->getInfoByOrderRecord($orderRecordIds, null);
        if (empty($orderPayRecords)) {
            return array();
        }

        $hotelLogic = A('Common/Hotel', 'Logic');
        $payInfo = $hotelLogic->getHotelPay($hotelId, true, null, true);
        $payInfo = getArrayValueAsIndex($payInfo, 'id');

        // 获取其他消费条目
        $otherCostInfo = $hotelLogic->getHotelOtherCost($hotelId, true);
        $otherCostInfo = getArrayValueAsIndex($otherCostInfo, 'id');

        // 获取系统货币
        $currencyLogic = A('Common/Currency', 'Logic');
        $currencyData = $currencyLogic->getBpCurrency();
        $currencyData = getArrayValueAsIndex($currencyData, 'id');

        // 添加支付方式名
        foreach ($orderPayRecords as $key => &$orderPayRecord) {
            if ($withBack === false) {
                // 不获取 退款 退押金
                if (in_array($orderPayRecord['type'], [PAY_CHANGE_REFUND,PAY_CHANGE_DEPOSIT_BACK])) {
                    unset($orderPayRecords[$key]);
                }
            }

            if (in_array($orderPayRecord['type'], [0,1,2,3])) {
                $orderPayRecord['name'] = $payInfo[$orderPayRecord['hotelpay_id']]['name'];
            } else {
                if ($orderPayRecord['hotelpay_id'] == 0) {
                    // 其他消费 待收款
                    $orderPayRecord['name'] = $this->payChangeTypeMap[LANG_SET][4];
                } else if ($orderPayRecord['hotelpay_id'] != 0 && !in_array($orderPayRecord['type'], [0,1,2,3])) {
                    // 其他消费 已收款
                    $orderPayRecord['name'] = $payInfo[$orderPayRecord['hotelpay_id']]['name'];
                }
                // // 其他消费项目
                $orderPayRecord['otherCostName'] = $otherCostInfo[$orderPayRecord['type']]['name'];
            }
            // 货币符号
            $orderPayRecord['symbol'] = isset($currencyData[$orderPayRecord['currency_id']]['symbol']) ? $currencyData[$orderPayRecord['currency_id']]['symbol'] : '¥';
        }
        unset($orderPayRecord);
        $orderPayRecords = array_values($orderPayRecords);

        return $orderPayRecords;
    }

    /**
     * 获取订单操作历史
     * 方法会抛异常
     * @modify trainyao 2016-01-05 创建
     * @param  integer   $hotelId   客栈id
     * @param  integer   $orderId   订单id
     * @return array                订单信息数组
     */
    public function getHistory($hotelId, $orderId) {
        try {
            $orderInfo = $this->getOrderInfo($hotelId, array($orderId));
        } catch (\Exception $e) {
            throw $e;
            return array();
        }

        // 获取修改记录s
        $orderRecordModel = D('OrderRecord');
        $orderRecords = $orderRecordModel->getInfoByOrder($orderId);
        if (empty($orderRecords)) {
            return array();
        }
        $orderRecords = getArrayValueAsIndex($orderRecords, 'id');

        // 统计订单,房间,用户改变了的记录
        $orderChange = array();
        $roomChange = array();
        $userChange = array();
        $orderPayRecordChange = array();
        $checkChange = array();
        foreach ($orderRecords as $orderRecord) {
            if ($orderRecord['order'] == 1) {
                array_push($orderChange, $orderRecord['id']);
            }
            if ($orderRecord['room'] == 1) {
                array_push($roomChange, $orderRecord['id']);
            }
            if ($orderRecord['user'] == 1) {
                array_push($userChange, $orderRecord['id']);
            }
            if ($orderRecord['orderpayrecord'] == 1) {
                array_push($orderPayRecordChange, $orderRecord['id']);
            }
            if ($orderRecord['check'] == 1) {
                array_push($checkChange, $orderRecord['id']);
            }
        }

        // 获取修改记录的订单修改记录,入住人修改记录,房间修改记录
        if (!empty($orderChange)) {
            $orderInfoRecordModel = D('OrderInfoRecord');
            $orderInfoRecords = $orderInfoRecordModel->getInfoByOrderRecord($orderChange);
            foreach ($orderInfoRecords as $orderInfoRecord) {
                if (empty($orderRecords[$orderInfoRecord['orderrecord_id']]['infoChange'])) {
                    $orderRecords[$orderInfoRecord['orderrecord_id']]['infoChange'] = array();
                }
                array_push($orderRecords[$orderInfoRecord['orderrecord_id']]['infoChange'], $orderInfoRecord);
            }
        }
        if (!empty($roomChange)) {
            $orderRoomRecordModel = D('OrderRoomRecord');
            $orderRoomRecords = $orderRoomRecordModel->getInfoByOrderRecord($roomChange);
            foreach ($orderRoomRecords as $orderRoomRecord) {
                if (empty($orderRecords[$orderRoomRecord['orderrecord_id']]['roomChange'])) {
                    $orderRecords[$orderRoomRecord['orderrecord_id']]['roomChange'] = array();
                }
                array_push($orderRecords[$orderRoomRecord['orderrecord_id']]['roomChange'], $orderRoomRecord);
            }
        }
        if (!empty($userChange)) {
            $orderUserRecordModel = D('OrderUserRecord');
            $orderUserRecords = $orderUserRecordModel->getInfoByOrderRecord($userChange);
            foreach ($orderUserRecords as $orderUserRecord) {
                if (empty($orderRecords[$orderUserRecord['orderrecord_id']]['userChange'])) {
                    $orderRecords[$orderUserRecord['orderrecord_id']]['userChange'] = array();
                }
                array_push($orderRecords[$orderUserRecord['orderrecord_id']]['userChange'], $orderUserRecord);
            }
        }
        if (!empty($orderPayRecordChange)) {
            $orderPayRecordInfoModel = D('OrderPayRecordInfo');
            $orderPayRecordInfos = $orderPayRecordInfoModel->getInfoByOrderRecord($orderPayRecordChange);
            foreach ($orderPayRecordInfos as &$orderPayRecordInfo) {
                // 是否待收款  待收款 hotelpay_id = 0
                if ($orderPayRecordInfo['hotelpay_id'] == 0 || $orderPayRecordInfo['hotelpay_id_before'] == 0) {
                    // 未支付  即 待收款
                    $orderPayRecordInfo['name'] = $this->payChangeTypeMap[LANG_SET][4];
                }

                if (empty($orderRecords[$orderPayRecordInfo['orderrecord_id']]['orderPayRecordChange'])) {
                    $orderRecords[$orderPayRecordInfo['orderrecord_id']]['orderPayRecordChange'] = array();
                }
                array_push($orderRecords[$orderPayRecordInfo['orderrecord_id']]['orderPayRecordChange'], $orderPayRecordInfo);
            }
        }
        if (!empty($checkChange)) {
            $orderRoomCheckRecordModel = D('OrderRoomCheckRecord');
            $orderRoomCheckRecords = $orderRoomCheckRecordModel->getInfoByOrderRecord($checkChange);
            foreach ($orderRoomCheckRecords as $orderCheckRoomRecord) {
                if (empty($orderRecords[$orderCheckRoomRecord['orderrecord_id']]['checkChange'])) {
                    $orderRecords[$orderCheckRoomRecord['orderrecord_id']]['checkChange'] = array();
                }
                array_push($orderRecords[$orderCheckRoomRecord['orderrecord_id']]['checkChange'], $orderCheckRoomRecord);
            }
        }

        // 补充支付方式修改历史
        $orderRecordIds = array_keys($orderRecords);
        $orderPayRecords = $this->getPayHistoryData($hotelId, $orderRecordIds, true);

        // 支付信息变化加入订单变化
        $orderPayRecords = getArrayValueAsIndex($orderPayRecords, 'orderrecord_id', true);
        foreach ($orderPayRecords as $orderRecordId => $orderPayRecord) {
            $orderRecords[$orderRecordId]['payChange'] = $orderPayRecord;
        }
        unset($orderPayRecords);

        // 取出客栈支付方式与分销渠道资源
        $hotelLogic = A('Common/Hotel', 'Logic');
        $channelInfo = $hotelLogic->getHotelChannel($hotelId);
        $hotelPayInfo = $hotelLogic->getHotelPay($hotelId);
        $channelInfo = getArrayValueAsIndex($channelInfo, 'id');
        $hotelPayInfo = getArrayValueAsIndex($hotelPayInfo, 'id');

        $brief = $this->generateBrief($hotelId, $orderRecords, $channelInfo, $hotelPayInfo); 
        $orderInfo[0]['change'] = $brief;

        return $orderInfo[0];
    }

    /**
     * 封装过滤前端需要显示的订单逻辑
     * @modify trainyao 2016-03-21    创建
     * @param array    $orders   过滤前订单数据
     * @param array    $startDate   查询区间开始 YYYY-mm-dd
     * @param array    $endDate   查询区间结束 YYYY-mm-dd
     * @return array   过滤后订单数据
     */
    public function filteFrontActiveOrder($orders, $startDate = null, $endDate = null) {
        // 过期订单不显示
        // 退房订单,取消订单实住为零不显示
        foreach ($orders as $index => $order) {
            if (in_array($order['status'], array(ORDER_OUTDATED)) || ($order['realnight'] == 0 && $order['hour'] == 0)) {
                unset($orders[$index]);
            }
            // 如果退房日期在开始日期那天或之前
            if ((substr($order['checkoutdate'], 0, 10) <= $startDate) && $order['hour'] == 0) {
                unset($orders[$index]);
            }
            // 过滤当天凌晨下的已退房的订单
            if (in_array($order['status'], array(ORDER_CHECKOUTED)) && $order['ismidnightorder'] == 1 && date('Y-m-d', strtotime($order['enddate'])) >= date('Y-m-d')) {
                unset($orders[$index]);
            }
        }
        unset($order);
        return array_values($orders);
    }

    /**
     * 生成概要数组
     * @modify trainyao 2016-01-05   创建
     * @modify AmosZhong 2016-05-20 修改，添加预订端操作者信息读取
     * @modify zhangzhen 2017-03-10 修改分享号码
     * @param  integer   $hotelId   客栈ID
     * @param  array   $changeArray 订单修改记录数组
     * @param  array   $channelInfo     分销渠道信息数组
     * @param  array   $hotelPayInfo     客栈支付方式信息数组
     * @return array                概要数组
     */
    private function generateBrief($hotelId, $changeArray, $channelInfo, $hotelPayInfo) {

        $output = array();
        $bookOperatorIds = array();
        $operatorIds = array();
        foreach ($changeArray as $change) {
            if ($change['recordfrom'] == ORDER_CHANGE_BOOK_WEB) {
                array_push($bookOperatorIds, $change['creator']);
            } else {
                array_push($operatorIds, $change['creator']);
            }
        }
        // 获取预订端操作人名称
        $bookOperatorIds = array_unique($bookOperatorIds);
        $userLoginModel = D('UserLogin');
        // TODO : 此处getInfo考虑放到用户逻辑处缓存着 ↓
        $bookOperators = $userLoginModel->getInfo($bookOperatorIds);
        if (count($bookOperatorIds) == 1) {
            $bookOperators = array($bookOperators);
        }
        $bookOperators = getArrayValueAsIndex($bookOperators, 'id');

        // 获取操作人名称
        $operatorIds = array_unique($operatorIds);

        $adminLoginModel = D('AdminLogin');
        // 此处getInfo考虑放到用户逻辑处缓存着 ↓
        $operators = $adminLoginModel->getInfo($operatorIds);
        if (count($operatorIds) == 1) {
            $operators = array($operators);
        }
        $operators = getArrayValueAsIndex($operators, 'id');
        $operators[0] = array('name' => '掌柜');

        // 获取消费项目条目
        $hotelLogic = A('Common/Hotel', 'Logic');
        $hotelOtherCostInfo = $hotelLogic->getHotelOtherCost($hotelId);
        $otherCostInfo = getArrayValueAsIndex($hotelOtherCostInfo, 'id');

        // 获取查房物品消费条目
        $hotelRoomCostData = $hotelLogic->getCheckRoomCost($hotelId, true);
        $hotelRoomCostData = getArrayValueAsIndex($hotelRoomCostData, 'id');

        // 获取客栈默认货币符号
        $currencyLogic = A('Common/Currency', 'Logic');
        $defaultCurrency = $currencyLogic->takeHotelCurrency($hotelId, ture);
        $symbol = isset($defaultCurrency[0]['symbol']) ? $defaultCurrency[0]['symbol'] : '¥';

        // 操作来源映射表
        $fromMap = array(
            'zh_cn' => array(
                ORDER_CHANGE_WEB => '美住网页端',
                ORDER_CHANGE_APP => '美住APP端',
                ORDER_CHANGE_BOOK_WEB => '美住WEB预定端',
            ),
            'en_us' => array(
                ORDER_CHANGE_WEB => 'Meizhu WEB',
                ORDER_CHANGE_APP => 'Meizhu APP',
                ORDER_CHANGE_BOOK_WEB => 'Meizhu WEB Booking',
            ),
            'zh_tw' => array(
                ORDER_CHANGE_WEB => '美住網頁端',
                ORDER_CHANGE_APP => '美住APP端',
                ORDER_CHANGE_BOOK_WEB => '美住WEB預定端',
            ),
        );

        $vipUserModel = D('VipUser');
        // 判断是否有权限查看信息
        $canSeeMobile = true;
        if (MODULE_NAME != 'Extend') {
            $adminAuthorityLogic = A('Common/AdminAuthority', 'Logic');
            $canSeeMobile = $adminAuthorityLogic->check($hotelId, null, AUTHORITY_CONTACT_INFO_BLOCK);
        }
        // 循环生成概要
        foreach ($changeArray as $change) {
            $onceChange = array();
            $onceChange['time'] = $change['createtime'];
            $onceChange['from'] = $fromMap[LANG_SET][$change['recordfrom']];

            if ($change['recordfrom'] == ORDER_CHANGE_BOOK_WEB) {
                $operatorName = $bookOperators[$change['creator']]['name'];
                if (empty($operatorName)) {
                    $operatorName = $bookOperators[$change['creator']]['mobile'];
                }
            } else {
                $operatorName = $operators[$change['creator']]['name'];
            }
            $onceChange['by'] = $operatorName;

            $detail = '';
            // 订单金额变化
            if ($change['payment'] != 0) {
                // 订单金额 加上其他消费已收的
                $otherReceivePrice = 0;
                if (!empty($change['payChange'])) {
                    foreach ($change['payChange'] as $payChange) {
                        if ($payChange['hotelpay_id'] != 0 && !in_array($payChange['type'], [0,1,2,3])) {
                            $otherReceivePrice += $payChange['pay'];
                        }
                    }
                }
                $change['payment'] = number_format($change['payment'] + $otherReceivePrice, '2', '.', '');

                switch (LANG_SET) {
                    case 'zh_cn':
                        $detail .= $change['payment'] > 0 ? '订单总金额+' . $symbol . $change['payment'] . ';' : '订单总金额' . $symbol . $change['payment'] . ';';
                        break;
                    case 'en_us':
                        $detail .= $change['payment'] > 0 ? 'Total amount of orders+' . $symbol . $change['payment'] . ';' : 'Total amount of orders' . $symbol . $change['payment'] . ';';
                        break;
                    case 'zh_tw':
                        $detail .= $change['payment'] > 0 ? '訂單總金額+' . $symbol . $change['payment'] . ';' : '訂單總金額' . $symbol . $change['payment'] . ';';
                        break;
                    default:
                        $detail .= $change['payment'] > 0 ? '订单总金额+' . $symbol . $change['payment'] . ';' : '订单总金额' . $symbol . $change['payment'] . ';';
                        break;
                }
            }

            if (!empty($change['payChange'])) {
                foreach ($change['payChange'] as $payChange) {
                    // 是否有会员卡支付
                    if ($payChange['vipuser_id'] != '0') {
                        $vipUserInfo = $vipUserModel->getInfoById($payChange['vipuser_id']);
                    }
                    $vipUserMobile = isset($vipUserInfo['mobile']) ? $vipUserInfo['mobile'] : '';

                    $payChange['pay'] = $payChange['firstpay'] == 0.00 ? $payChange['pay'] : $payChange['firstpay'];
                    switch (LANG_SET) {
                        case 'en_us':
                           switch ($payChange['type']) {
                                case PAY_CHANGE_RECEIPT :
                                    $detail .= 'By[' . $vipUserMobile . $payChange['name'] . ']receipt' . $symbol . $payChange['pay'] . ';';
                                    break;
                                case PAY_CHANGE_DEPOSIT :
                                    $detail .= 'By[' . $vipUserMobile . $payChange['name'] . ']receipt guarantee deposit' . $symbol . $payChange['pay'] . ';';
                                    break;
                                case PAY_CHANGE_REFUND :
                                    $detail .= 'refund' .  $symbol . $payChange['pay'] . ' by' . $payChange['name'];
                                    break;
                                case PAY_CHANGE_DEPOSIT_BACK :
                                    $detail .= 'refund guarantee deposit ' .  $symbol . $payChange['pay'] . ' by' . $payChange['name'];
                                    break;
                                default:
                                    if ($payChange['hotelpay_id'] == 0) {
                                        $detail .= '[Other consumption--' . $otherCostInfo[$payChange['type']]['name'] . ' ' . $vipUserMobile . $payChange['name'] . '] ' . $symbol . $payChange['pay'] . ';';
                                    } else {
                                         $detail .= '[Other consumption--' . $otherCostInfo[$payChange['type']]['name'] . ' ' . $vipUserMobile . $payChange['name'] . ']receipt' . $symbol . $payChange['pay'] . ';';
                                    }
                                    break;
                            }
                            break;
                        case 'zh_tw':
                            switch ($payChange['type']) {
                                case PAY_CHANGE_RECEIPT :
                                    $detail .= '通過[' . $vipUserMobile . $payChange['name'] . ']收款' . $symbol . $payChange['pay'] . ';';
                                    break;
                                case PAY_CHANGE_DEPOSIT :
                                    $detail .= '通過[' . $vipUserMobile . $payChange['name'] . ']收取押金' . $symbol . $payChange['pay'] . ';';
                                    break;
                                case PAY_CHANGE_REFUND :
                                    $detail .= '從[' . $payChange['name'] . ']退款' . $symbol . $payChange['pay'] . ';';
                                    break;
                                case PAY_CHANGE_DEPOSIT_BACK :
                                    $detail .= '從[' . $payChange['name'] . ']退還押金' . $symbol . $payChange['pay'] . ';';
                                    break;
                                default:
                                    if ($payChange['hotelpay_id'] == 0) {
                                        $detail .= '[其他消费--' . $otherCostInfo[$payChange['type']]['name'] . ' ' . $vipUserMobile . $payChange['name'] . '] ' . $symbol . $payChange['pay'] . ';';
                                    } else {
                                        $detail .= '[其他消费--' . $otherCostInfo[$payChange['type']]['name'] . ' ' . $vipUserMobile . $payChange['name'] . ']收款' . $symbol . $payChange['pay'] . ';';
                                    }
                                    break;
                            }
                            break;
                        default:
                            switch ($payChange['type']) {
                                case PAY_CHANGE_RECEIPT :
                                    $detail .= '通过[' . $vipUserMobile . $payChange['name'] . ']收款' . $symbol . $payChange['pay'] . ';';
                                    break;
                                case PAY_CHANGE_DEPOSIT :
                                    $detail .= '通过[' . $vipUserMobile . $payChange['name'] . ']收取押金' . $symbol . $payChange['pay'] . ';';
                                    break;
                                case PAY_CHANGE_REFUND :
                                    $detail .= '从[' . $payChange['name'] . ']退款' . $symbol . $payChange['pay'] . ';';
                                    break;
                                case PAY_CHANGE_DEPOSIT_BACK :
                                    $detail .= '从[' . $payChange['name'] . ']退还押金' . $symbol . $payChange['pay'] . ';';
                                    break;
                                default:
                                    if ($payChange['hotelpay_id'] == 0) {
                                        $detail .= '[其他消费--' . $otherCostInfo[$payChange['type']]['name'] . ' ' . $vipUserMobile . $payChange['name'] . '] ' . $symbol . $payChange['pay'] . ';';
                                    } else {
                                        $detail .= '[其他消费--' . $otherCostInfo[$payChange['type']]['name'] . ' ' . $vipUserMobile . $payChange['name'] . ']收款' . $symbol . $payChange['pay'] . ';';
                                    }
                                    break;
                            }
                            break;
                    }
                }
            }
            if (!empty($detail)) {
                $onceChange['p'] = $detail;
            }

            // 订单基本信息变化
            if ($change['order']) {
                $detail = '';
                $changeInfo = $change['infoChange'][0];
                // 选择语言
                switch (LANG_SET) {
                    case 'en_us':
                        if ($changeInfo['hotelchannel_id'] != $changeInfo['hotelchannel_before']) {
                            if (empty($changeInfo['remark_before'])) {
                                $detail .= 'payment way is "' . $channelInfo[$changeInfo['hotelchannel_id']]['name'] . '";';
                            } else {
                                $detail .= 'payment way instead "' . $channelInfo[$changeInfo['hotelchannel_id']]['name'] . '"by"' . $channelInfo[$changeInfo['hotelchannel_before']]['name'] . '";';
                            }
                        }
                        if ($changeInfo['mobile'] != $changeInfo['mobile_before'] || $changeInfo['name'] != $changeInfo['name_before']) {
                            if ($changeInfo['mobile_before'] == '' && $changeInfo['name_before'] == '') {
                                $detail .= 'Booking person:' . $changeInfo['name'];
                                $detail .= $changeInfo['mobile'] ? ('[' . ($canSeeMobile ? $changeInfo['mobile'] : substr($changeInfo['mobile'], 0, 3) . '********') . '];') : ';';
                            } else {
                                $detail .= 'booking person instead"' . $changeInfo['name'] . '"';
                                $detail .= $changeInfo['mobile'] ? ('[' . '+' . $changeInfo['areacode'] . ' ' . ($canSeeMobile ? $changeInfo['mobile'] : substr($changeInfo['mobile'], 0, 3) . '********') . '];') : ';';
                                $detail .= 'by"' . $changeInfo['name_before'] . '"';
                                $detail .= $changeInfo['mobile_before'] ? ('[' . '+' . $changeInfo['areacode_before'] . ' ' . ($canSeeMobile ? $changeInfo['mobile_before'] : substr($changeInfo['mobile_before'], 0, 3) . '********') . ']') : '';
                            }
                        }
                        if ($changeInfo['identity'] != $changeInfo['identity_before']) {
                            if (empty($changeInfo['identity_before'])) {
                                $detail .= 'Input booking person ID card:' . $changeInfo['identity'] . ';';
                            } else {
                                $detail .= 'ID Card of booking person instead "' . $changeInfo['identity'] . '"by"' . $changeInfo['identity_before'] . '";';
                            }
                        }
                        if ($changeInfo['remark'] != $changeInfo['remark_before']) {
                            if (empty($changeInfo['remark_before'])) {
                                $detail .= 'Remarks:' . $changeInfo['remark'] . ';';
                            } else {
                                $detail .= 'Remarks change from "' . $changeInfo['remark_before'] . (empty($changeInfo['remark']) ? '"Empty;' : ('"to"' . $changeInfo['remark'] . '";'));
                            }
                        }
                        break;
                    case 'zh_tw':
                        if ($changeInfo['hotelchannel_id'] != $changeInfo['hotelchannel_before']) {
                            if (empty($changeInfo['remark_before'])) {
                                $detail .= '支付渠道為"' . $channelInfo[$changeInfo['hotelchannel_id']]['name'] . '";';
                            } else {
                                $detail .= '支付渠道由"' . $channelInfo[$changeInfo['hotelchannel_before']]['name'] . '"改為"' . $channelInfo[$changeInfo['hotelchannel_id']]['name'] . '";';
                            }
                        }
                        if ($changeInfo['mobile'] != $changeInfo['mobile_before'] || $changeInfo['name'] != $changeInfo['name_before']) {
                            if ($changeInfo['mobile_before'] == '' && $changeInfo['name_before'] == '') {
                                $detail .= '預定人:' . $changeInfo['name'];
                                $detail .= $changeInfo['mobile'] ? ('[' . ($canSeeMobile ? $changeInfo['mobile'] : substr($changeInfo['mobile'], 0, 3) . '********') . '];') : ';';
                            } else {
                                $detail .= '預定人由"' . $changeInfo['name_before'] . '"';
                                $detail .= $changeInfo['mobile_before'] ? ('[' . '+' . $changeInfo['areacode_before'] . ' ' . ($canSeeMobile ? $changeInfo['mobile_before'] : substr($changeInfo['mobile_before'], 0, 3) . '********') . ']') : '';
                                $detail .= '改為"' . $changeInfo['name'] . '"';
                                $detail .= $changeInfo['mobile'] ? ('[' . '+' . $changeInfo['areacode'] . ' ' . ($canSeeMobile ? $changeInfo['mobile'] : substr($changeInfo['mobile'], 0, 3) . '********') . '];') : ';';
                            }
                        }
                        if ($changeInfo['identity'] != $changeInfo['identity_before']) {
                            if (empty($changeInfo['identity_before'])) {
                                $detail .= '輸入預訂人身份證:' . $changeInfo['identity'] . ';';
                            } else {
                                $detail .= '預定人身份證由"' . $changeInfo['identity_before'] . '"改為"' . $changeInfo['identity'] . '";';
                            }
                        }
                        if ($changeInfo['remark'] != $changeInfo['remark_before']) {
                            if (empty($changeInfo['remark_before'])) {
                                $detail .= '備註:' . $changeInfo['remark'] . ';';
                            } else {
                                $detail .= '備註由"' . $changeInfo['remark_before'] . (empty($changeInfo['remark']) ? '"置空;' : ('"改為"' . $changeInfo['remark'] . '";'));
                            }
                        }
                        break;
                    default:
                        if ($changeInfo['hotelchannel_id'] != $changeInfo['hotelchannel_before']) {
                            if (empty($changeInfo['remark_before'])) {
                                $detail .= '支付渠道为"' . $channelInfo[$changeInfo['hotelchannel_id']]['name'] . '";';
                            } else {
                                $detail .= '支付渠道由"' . $channelInfo[$changeInfo['hotelchannel_before']]['name'] . '"改为"' . $channelInfo[$changeInfo['hotelchannel_id']]['name'] . '";';
                            }
                        }
                        if ($changeInfo['mobile'] != $changeInfo['mobile_before'] || $changeInfo['name'] != $changeInfo['name_before']) {
                            if ($changeInfo['mobile_before'] == '' && $changeInfo['name_before'] == '') {
                                $detail .= '预定人:' . $changeInfo['name'];
                                $detail .= $changeInfo['mobile'] ? ('[' . ($canSeeMobile ? $changeInfo['mobile'] : substr($changeInfo['mobile'], 0, 3) . '********') . '];') : ';';
                            } else {
                                $detail .= '预定人由"' . $changeInfo['name_before'] . '"';
                                $detail .= $changeInfo['mobile_before'] ? ('[' . '+' . $changeInfo['areacode_before'] . ' ' . ($canSeeMobile ? $changeInfo['mobile_before'] : substr($changeInfo['mobile_before'], 0, 3) . '********') . ']') : '';
                                $detail .= '改为"' . $changeInfo['name'] . '"';
                                $detail .= '+' . $changeInfo['areacode'] . $changeInfo['mobile'] ? ('[' . '+' . $changeInfo['areacode'] . ' ' . ($canSeeMobile ? $changeInfo['mobile'] : substr($changeInfo['mobile'], 0, 3) . '********') . '];') : ';';
                            }
                        }
                        if ($changeInfo['identity'] != $changeInfo['identity_before']) {
                            if (empty($changeInfo['identity_before'])) {
                                $detail .= '录入预定人身份证:' . $changeInfo['identity'] . ';';
                            } else {
                                $detail .= '预定人身份证由"' . $changeInfo['identity_before'] . '"改为"' . $changeInfo['identity'] . '";';
                            }
                        }
                        if ($changeInfo['remark'] != $changeInfo['remark_before']) {
                            if (empty($changeInfo['remark_before'])) {
                                $detail .= '备注:' . $changeInfo['remark'] . ';';
                            } else {
                                $detail .= '备注由"' . $changeInfo['remark_before'] . (empty($changeInfo['remark']) ? '"置空;' : ('"改为"' . $changeInfo['remark'] . '";'));
                            }
                        }
                        break;
                }
                $onceChange['i'] = $detail;
            }

            // 订单房间信息变化
            if ($change['room']) {
                $detail = '';
                switch (LANG_SET) {
                    case 'en_us':
                        foreach ($change['roomChange'] as $index => $roomChange) {
                            switch ($roomChange['type']) {
                                case ORDER_CHANGE_DELETE:
                                    $detail .= 'cancel[' . $this->statusMap[LANG_SET][$roomChange['status_before']] . ']Sub-order"' . $roomChange['roomtype_name_before'] . '-' . $roomChange['roominfo_name_before'] . '"';
                                    break;
                                case ORDER_CHANGE_ADD:
                                    $detail .= ($index == 0 ? 'input"' : 'add"') . $roomChange['roomtype_name'] . '-' . $roomChange['roominfo_name'] . '"Sub-order,amount ' . $symbol . $roomChange['payment'] . ',date' . substr($roomChange['startdate'],
                                                    0, 10) . 'to' . substr($roomChange['enddate'], 0, 10) . ';';
                                    break;
                                case ORDER_CHANGE_EDIT:
                                    // 生成变化头部
                                    $detail .= 'Sub-order"' . $roomChange['roomtype_name_before'] . '-' . $roomChange['roominfo_name_before'] . '"';
                                    // 处理变化
                                    $detailArray = array();
                                    if ($roomChange['status_before'] != $roomChange['status']) {
                                        switch ($roomChange['status']) {
                                            case ORDER_CHECKOUTED:
                                                array_push($detailArray, 'Check out');
                                                break;
                                            case ORDER_CANCELED:
                                                array_push($detailArray, 'Be canceled');
                                                break;
                                            case ORDER_CHECKINED:
                                                array_push($detailArray, 'Check in');
                                                break;
                                            default:
                                                array_push($detailArray, 'Order state[' . $this->statusMap[LANG_SET][$roomChange['status_before']] . ']instead[' . $this->statusMap[LANG_SET][$roomChange['status']] . ']');
                                                break;
                                        }
                                    }

                                    // 订单状态没变化,或者订单状态变化后不为[已过期,已取消,已入住,已退房]
                                    if (($roomChange['status_before'] == $roomChange['status']) || ($roomChange['status_before'] != $roomChange['status'] && !in_array($roomChange['status'], array(ORDER_OUTDATED, ORDER_CANCELED, ORDER_CHECKOUTED)))) {
                                        if ($roomChange['roominfo_name_before'] != $roomChange['roominfo_name'] || $roomChange['roomtype_name_before'] != $roomChange['roomtype_name']) {
                                            $detail .= 'Check in room  instead by what"' . $roomChange['roomtype_name'] . '-' . $roomChange['roominfo_name'] . '"';
                                        }

                                        if ($roomChange['startdate_before'] != $roomChange['startdate'] || $roomChange['enddate_before'] !=
                                                $roomChange['enddate']) {
                                            array_push($detailArray, 'Check in time instead"' . substr($roomChange['startdate'], 0, 10) . '-' . substr($roomChange['enddate'], 0, 10) . '"by"' . substr($roomChange['startdate_before'], 0, 10) . '-' . substr($roomChange['enddate_before'], 0, 10) . '"');
                                        }
                                        if ($roomChange['payment_before'] != $roomChange['payment']) {
                                            array_push($detailArray, 'Sub-order amount instead ' . $symbol . $roomChange['payment'] . ' by ' . $symbol . $roomChange['payment_before']);
                                        }
                                    }
                                    $detailArray = implode(',', $detailArray);
                                    $detail .= $detailArray . ';';
                                    break;
                            }
                            $detail .= '\n';
                        }
                        break;
                    case 'zh_tw':
                        foreach ($change['roomChange'] as $index => $roomChange) {
                            switch ($roomChange['type']) {
                                case ORDER_CHANGE_DELETE:
                                    $detail .= '取消[' . $this->statusMap[LANG_SET][$roomChange['status_before']] . ']子訂單"' . $roomChange['roomtype_name_before'] . '-' . $roomChange['roominfo_name_before'] . '"';
                                    break;
                                case ORDER_CHANGE_ADD:
                                    $detail .= ($index == 0 ? '錄入"' : '添加"') . $roomChange['roomtype_name'] . '-' . $roomChange['roominfo_name'] . '"子訂單,訂單金額為' . $roomChange['payment'] . '元,入住日期' . substr($roomChange['startdate'],
                                                    0, 10) . '至' . substr($roomChange['enddate'], 0, 10) . ';';
                                    break;
                                case ORDER_CHANGE_EDIT:
                                    // 生成变化头部
                                    $detail .= '子訂單"' . $roomChange['roomtype_name_before'] . '-' . $roomChange['roominfo_name_before'] . '"';
                                    // 处理变化
                                    $detailArray = array();
                                    if ($roomChange['status_before'] != $roomChange['status']) {
                                        switch ($roomChange['status']) {
                                            case ORDER_CHECKOUTED:
                                                array_push($detailArray, '辦理退房');
                                                break;
                                            case ORDER_CANCELED:
                                                array_push($detailArray, '被取消');
                                                break;
                                            case ORDER_CHECKINED:
                                                array_push($detailArray, '辦理入住');
                                                break;
                                            default:
                                                array_push($detailArray, '訂單狀態[' . $this->statusMap[LANG_SET][$roomChange['status_before']] . ']改為[' . $this->statusMap[LANG_SET][$roomChange['status']] . ']');
                                                break;
                                        }
                                    }

                                    // 订单状态没变化,或者订单状态变化后不为[已过期,已取消,已入住,已退房]
                                    if (($roomChange['status_before'] == $roomChange['status']) || ($roomChange['status_before'] != $roomChange['status'] && !in_array($roomChange['status'], array(ORDER_OUTDATED, ORDER_CANCELED, ORDER_CHECKOUTED)))) {
                                        if ($roomChange['roominfo_name_before'] != $roomChange['roominfo_name'] || $roomChange['roomtype_name_before'] != $roomChange['roomtype_name']) {
                                            $detail .= '入住房間修改為"' . $roomChange['roomtype_name'] . '-' . $roomChange['roominfo_name'] . '"';
                                        }

                                        if ($roomChange['startdate_before'] != $roomChange['startdate'] || $roomChange['enddate_before'] !=
                                                $roomChange['enddate']) {
                                            array_push($detailArray, '入住日期由"' . substr($roomChange['startdate_before'], 0, 10) . '至' . substr($roomChange['enddate_before'], 0, 10) . '"改為"' . substr($roomChange['startdate'], 0, 10) . '至' . substr($roomChange['enddate'], 0, 10) . '"');
                                        }
                                        if ($roomChange['payment_before'] != $roomChange['payment']) {
                                            array_push($detailArray, '子訂單金額由' . $symbol . $roomChange['payment_before'] . '改為' . $symbol . $roomChange['payment']);
                                        }
                                    }
                                    $detailArray = implode(',', $detailArray);
                                    $detail .= $detailArray . ';';
                                    break;
                            }
                            $detail .= '\n';
                        }
                        break;
                    default:
                        foreach ($change['roomChange'] as $index => $roomChange) {
                            switch ($roomChange['type']) {
                                case ORDER_CHANGE_DELETE:
                                    $detail .= '取消[' . $this->statusMap[LANG_SET][$roomChange['status_before']] . ']子订单"' . $roomChange['roomtype_name_before'] . '-' . $roomChange['roominfo_name_before'] . '"';
                                    break;
                                case ORDER_CHANGE_ADD:
                                    $detail .= ($index == 0 ? '录入"' : '添加"') . $roomChange['roomtype_name'] . '-' . $roomChange['roominfo_name'] . '"子订单,订单金额为' . $symbol . $roomChange['payment'] . ',入住日期' . substr($roomChange['startdate'],
                                                    0, 10) . '至' . substr($roomChange['enddate'], 0, 10) . ';';
                                    break;
                                case ORDER_CHANGE_EDIT:
                                    // 生成变化头部
                                    $detail .= '子订单"' . $roomChange['roomtype_name_before'] . '-' . $roomChange['roominfo_name_before'] . '"';
                                    // 处理变化
                                    $detailArray = array();
                                    if ($roomChange['status_before'] != $roomChange['status']) {
                                        switch ($roomChange['status']) {
                                            case ORDER_CHECKOUTED:
                                                array_push($detailArray, '办理退房');
                                                break;
                                            case ORDER_CANCELED:
                                                array_push($detailArray, '被取消');
                                                break;
                                            case ORDER_CHECKINED:
                                                array_push($detailArray, '办理入住');
                                                break;
                                            default:
                                                array_push($detailArray, '订单状态[' . $this->statusMap[LANG_SET][$roomChange['status_before']] . ']改为[' . $this->statusMap[LANG_SET][$roomChange['status']] . ']');
                                                break;
                                        }
                                    }

                                    // 订单状态没变化,或者订单状态变化后不为[已过期,已取消,已入住,已退房]
                                    if (($roomChange['status_before'] == $roomChange['status']) || ($roomChange['status_before'] != $roomChange['status'] && !in_array($roomChange['status'], array(ORDER_OUTDATED, ORDER_CANCELED, ORDER_CHECKOUTED)))) {
                                        if ($roomChange['roominfo_name_before'] != $roomChange['roominfo_name'] || $roomChange['roomtype_name_before'] != $roomChange['roomtype_name']) {
                                            $detail .= '入住房间修改为"' . $roomChange['roomtype_name'] . '-' . $roomChange['roominfo_name'] . '"';
                                        }

                                        if ($roomChange['startdate_before'] != $roomChange['startdate'] || $roomChange['enddate_before'] !=
                                                $roomChange['enddate']) {
                                            array_push($detailArray, '入住日期由"' . substr($roomChange['startdate_before'], 0, 10) . '至' . substr($roomChange['enddate_before'], 0, 10) . '"改为"' . substr($roomChange['startdate'], 0, 10) . '至' . substr($roomChange['enddate'], 0, 10) . '"');
                                        }
                                        if ($roomChange['payment_before'] != $roomChange['payment']) {
                                            array_push($detailArray, '子订单金额由' . $symbol . $roomChange['payment_before'] . '改为' . $symbol . $roomChange['payment']);
                                        }
                                    }
                                    $detailArray = implode(',', $detailArray);
                                    $detail .= $detailArray . ';';
                                    break;
                            }
                            $detail .= '\n';
                        }
                        break;
                }
                $onceChange['r'] = $detail;
            }

            // 订单入住人信息变化
            if ($change['user']) {
                $detail = '';
                switch (LANG_SET) {
                    case 'en_us':
                        foreach ($change['userChange'] as $index => $userChange) {
                            switch ($userChange['type']) {
                                case '0':
                                    $detail .= 'Delete lodger"' . $userChange['name_before'];
                                    $detail .= $userChange['mobile_before'] ? ('[' . ($canSeeMobile ? $userChange['mobile_before'] : substr($userChange['mobile_before'], 0, 3) . '********') . ']";') : '";';
                                    break;
                                case '1':
                                    $detail .= ($index == 0 ? 'lodger"' : 'add lodger"') . $userChange['name'];
                                    $detail .= $userChange['mobile'] ? ('[' . ($canSeeMobile ? $userChange['mobile'] : substr($userChange['mobile'], 0, 3) . '********') . ']"') : '"';
                                    $detail .= empty($userChange['identity']) ? ';' : ('And input ID Card"' . $userChange['identity'] . '";');
                                    break;
                                case '2':
                                    $detail .= 'Check in person instead"' . $userChange['name'];
                                    $detail .= $userChange['identity'] ? ('(' . $userChange['identity'] . ')') : '';
                                    $detail .= $userChange['mobile'] ? ('[' . '+' . $changeInfo['areacode'] . ' '  . ($canSeeMobile ? $userChange['mobile'] : substr($userChange['mobile'], 0, 3) . '********') . ']";') : '";';
                                    $detail .= 'by"' . $userChange['name_before'];
                                    $detail .= $userChange['identity_before'] ? ('(' . $userChange['identity_before'] . ')') : '';
                                    $detail .= $userChange['mobile_before'] ? ('[' . '+' . $changeInfo['areacode_before'] . ' '   . ($canSeeMobile ? $userChange['mobile_before'] : substr($userChange['mobile_before'], 0, 3) . '********') . ']"') : '"';
                                    break;
                            }
                            $detail .= '\n';
                        }
                        break;
                    case 'zh_tw':
                        foreach ($change['userChange'] as $index => $userChange) {
                            switch ($userChange['type']) {
                                case '0':
                                    $detail .= '删除入住人"' . $userChange['name_before'];
                                    $detail .= $userChange['mobile_before'] ? ('[' . ($canSeeMobile ? $userChange['mobile_before'] : substr($userChange['mobile_before'], 0, 3) . '********') . ']";') : '";';
                                    break;
                                case '1':
                                    $detail .= ($index == 0 ? '房間入住人"' : '添加入住人"') . $userChange['name'];
                                    $detail .= $userChange['mobile'] ? ('[' . ($canSeeMobile ? $userChange['mobile'] : substr($userChange['mobile'], 0, 3) . '********') . ']"') : '"';
                                    $detail .= empty($userChange['identity']) ? ';' : ('並錄入身份證"' . $userChange['identity'] . '";');
                                    break;
                                case '2':
                                    $detail .= '入住人"' . $userChange['name_before'];
                                    $detail .= $userChange['identity_before'] ? ('(' . $userChange['identity_before'] . ')') : '';
                                    $detail .= $userChange['mobile_before'] ? ('[' . '+' . $changeInfo['areacode_before'] . ' '  . ($canSeeMobile ? $userChange['mobile_before'] : substr($userChange['mobile_before'], 0, 3) . '********') . ']"') : '"';
                                    $detail .= '修改為"' . $userChange['name'];
                                    $detail .= $userChange['identity'] ? ('(' . $userChange['identity'] . ')') : '';
                                    $detail .= $userChange['mobile'] ? ('[' . '+' . $changeInfo['areacode'] . ' '  . ($canSeeMobile ? $userChange['mobile'] : substr($userChange['mobile'], 0, 3) . '********') . ']";') : '";';
                                    break;
                            }
                            $detail .= '\n';
                        }
                        break;
                    default:
                        foreach ($change['userChange'] as $index => $userChange) {
                            switch ($userChange['type']) {
                                case '0':
                                    $detail .= '删除入住人"' . $userChange['name_before'];
                                    $detail .= $userChange['mobile_before'] ? ('[' . ($canSeeMobile ? $userChange['mobile_before'] : substr($userChange['mobile_before'], 0, 3) . '********') . ']";') : '";';
                                    break;
                                case '1':
                                    $detail .= ($index == 0 ? '房间入住人"' : '添加入住人"') . $userChange['name'];
                                    $detail .= $userChange['mobile'] ? ('[' . ($canSeeMobile ? $userChange['mobile'] : substr($userChange['mobile'], 0, 3) . '********') . ']"') : '"';
                                    $detail .= empty($userChange['identity']) ? ';' : ('并录入身份证"' . $userChange['identity'] . '";');
                                    break;
                                case '2':
                                    $detail .= '入住人"' . $userChange['name_before'];
                                    $detail .= $userChange['identity_before'] ? ('(' . $userChange['identity_before'] . ')') : '';
                                    $detail .= $userChange['mobile_before'] ? ('[' . '+' . $changeInfo['areacode_before'] . ' '  . ($canSeeMobile ? $userChange['mobile_before'] : substr($userChange['mobile_before'], 0, 3) . '********') . ']"') : '"';
                                    $detail .= '修改为"' . $userChange['name'];
                                    $detail .= $userChange['identity'] ? ('(' . $userChange['identity'] . ')') : '';
                                    $detail .= $userChange['mobile'] ? ('[' . '+' . $changeInfo['areacode'] . ' '  . ($canSeeMobile ? $userChange['mobile'] : substr($userChange['mobile'], 0, 3) . '********') . ']";') : '";';
                                    break;
                            }
                            $detail .= '\n';
                        }
                        break;
                }
                $onceChange['u'] = $detail;
            }

            // 订单支付记录信息变化
            if ($change['orderpayrecord']) {
                $detail = '';
                switch (LANG_SET) {
                    case 'en_us':
                    foreach ($change['orderPayRecordChange'] as $index => $orderPayRecordChange) {
                            // '类型0=收款 1= 押金 2=退款 3=退押金'
                            switch ($orderPayRecordChange['type_before']) {
                                case '0':
                                    $detail .= 'By ['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'].'] receipt '. $orderPayRecordChange['pay_before'].'￥';
                                    break;
                                case '1':
                                    $detail .= 'By ['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'].'] receipt guarantee deposit '. $orderPayRecordChange['pay_before'].'￥';
                                    break;
                                case '2':
                                   $detail .= 'By ['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'].'] refund '. $orderPayRecordChange['pay_before'].'￥';
                                    break;
                                case '3':
                                    $detail .= 'By ['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'].'] refund guarantee deposit '. $orderPayRecordChange['pay_before'].'￥';
                                    break;
                                default:
                                    if ($orderPayRecordChange['hotelpay_id_before'] == 0) {
                                        $detail .= 'By [Other consumption--'.$otherCostInfo[$orderPayRecordChange['type_before']]['name'].' '.$orderPayRecordChange['name'].'] '. $orderPayRecordChange['pay_before'].'￥';
                                    } else {
                                        $detail .= 'By [Other consumption--'.$otherCostInfo[$orderPayRecordChange['type_before']]['name'].' '.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'] . '] receipt ' . $orderPayRecordChange['pay_before'] . '￥';
                                    }
                                    break;
                            }

                            switch ($orderPayRecordChange['type']) {
                                case '0':
                                    $detail .= ' modify by ['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'].'] receipt '. $orderPayRecordChange['pay'].'￥';
                                    break;
                                case '1':
                                     $detail .= ' modify by ['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'].'] receipt guarantee deposit '. $orderPayRecordChange['pay'].'￥';
                                    break;
                                case '2':
                                     $detail .= ' modify by ['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'].'] refund '. $orderPayRecordChange['pay'].'￥';
                                    break;
                                case '3':
                                     $detail .= ' modify by ['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'].'] refund guarantee deposit '. $orderPayRecordChange['pay'].'￥';
                                    break;
                                default:
                                    if ($orderPayRecordChange['hotelpay_id'] == 0) {
                                        $detail .= ' modify by [Other consumption--'.$otherCostInfo[$orderPayRecordChange['type']]['name'].' '.$orderPayRecordChange['name'].'] '. $orderPayRecordChange['pay'].'￥';
                                    } else {
                                        $detail .= ' modify by [Other consumption--'.$otherCostInfo[$orderPayRecordChange['type']]['name'].' '.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'] . '] receipt ' . $orderPayRecordChange['pay'] . '￥';
                                    }
                                    break;
                            }
                            $detail .= '\n';
                        }
                        unset($orderPayRecordChange);
                        break;
                    case 'zh_tw':
                        foreach ($change['orderPayRecordChange'] as $index => $orderPayRecordChange) {
                            // '类型0=收款 1= 押金 2=退款 3=退押金'
                            switch ($orderPayRecordChange['type_before']) {
                                case '0':
                                    $detail .= '通過['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'].']收款'. $symbol . $orderPayRecordChange['pay_before'].'；';
                                    break;
                                case '1':
                                    $detail .= '通過['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'].']收取押金'. $symbol . $orderPayRecordChange['pay_before'].'；';
                                    break;
                                case '2':
                                   $detail .= '通過['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'].']退款'. $symbol . $orderPayRecordChange['pay_before'].'；';
                                    break;
                                case '3':
                                    $detail .= '通過['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'].']退押金'. $symbol . $orderPayRecordChange['pay_before'].'；';
                                    break;
                                default:
                                    if ($orderPayRecordChange['hotelpay_id_before'] == 0) {
                                        $detail .= '[其他消费--'.$otherCostInfo[$orderPayRecordChange['type_before']]['name'].' '.$orderPayRecordChange['name'].']'. $symbol . $orderPayRecordChange['pay_before'].'；';
                                    } else {
                                        $detail .= '[其他消费--'.$otherCostInfo[$orderPayRecordChange['type_before']]['name'].' '.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'] . ']收款' . $symbol . $orderPayRecordChange['pay_before'] . ';';
                                    }
                                    break;
                            }

                            switch ($orderPayRecordChange['type']) {
                                case '0':
                                    $detail .= '改為通過['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'].']收款'. $symbol . $orderPayRecordChange['pay'].'；';
                                    break;
                                case '1':
                                     $detail .= '改為通過['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'].']收取押金'. $symbol . $orderPayRecordChange['pay'].'；';
                                    break;
                                case '2':
                                     $detail .= '改為通過['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'].']退款'. $symbol . $orderPayRecordChange['pay'].'；';
                                    break;
                                case '3':
                                     $detail .= '改為通過['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'].']退押金'. $symbol . $orderPayRecordChange['pay'].'；';
                                    break;
                                default:
                                    if ($orderPayRecordChange['hotelpay_id'] == 0) {
                                        $detail .= '改為[其他消费--'.$otherCostInfo[$orderPayRecordChange['type']]['name'].' '.$orderPayRecordChange['name'].']'. $symbol . $orderPayRecordChange['pay'].'；';
                                     } else {
                                        $detail .= '改為[其他消费--'.$otherCostInfo[$orderPayRecordChange['type']]['name'].' '.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'].']收款' . $symbol . $orderPayRecordChange['pay'] . ';';
                                     }
                                    break;
                            }
                            $detail .= '\n';
                        }
                        unset($orderPayRecordChange);
                        break;
                    default:
                        foreach ($change['orderPayRecordChange'] as $index => $orderPayRecordChange) {
                            // '类型0=收款 1= 押金 2=退款 3=退押金'
                            switch ($orderPayRecordChange['type_before']) {
                                case '0':
                                    $detail .= '通过['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'].']收款'. $symbol . $orderPayRecordChange['pay_before'].'；';
                                    break;
                                case '1':
                                    $detail .= '通过['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'].']收取押金'. $symbol . $orderPayRecordChange['pay_before'].'；';
                                    break;
                                case '2':
                                   $detail .= '通过['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'].']退款'. $symbol . $orderPayRecordChange['pay_before'].'；';
                                    break;
                                case '3':
                                    $detail .= '通过['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'].']退押金'. $symbol . $orderPayRecordChange['pay_before'].'；';
                                    break;
                                default:                                
                                    if ($orderPayRecordChange['hotelpay_id_before'] == 0) {
                                        $detail .= '[其他消费--'.$otherCostInfo[$orderPayRecordChange['type_before']]['name'].' '.$orderPayRecordChange['name'].']'. $symbol . $orderPayRecordChange['pay_before'].'；';
                                    } else {
                                        $detail .= '[其他消费--'.$otherCostInfo[$orderPayRecordChange['type_before']]['name'].' '.$hotelPayInfo[$orderPayRecordChange['hotelpay_id_before']]['name'].']收款' . $symbol . $orderPayRecordChange['pay_before'] . ';';
                                    }
                                    break;
                            }

                            switch ($orderPayRecordChange['type']) {
                                case '0':
                                    $detail .= '改为通过['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'].']收款'. $symbol . $orderPayRecordChange['pay'].'；';
                                    break;
                                case '1':
                                     $detail .= '改为通过['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'].']收取押金'. $symbol . $orderPayRecordChange['pay'].'；';
                                    break;
                                case '2':
                                     $detail .= '改为通过['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'].']退款'. $symbol . $orderPayRecordChange['pay'].'；';
                                    break;
                                case '3':
                                     $detail .= '改为通过['.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'].']退押金'. $symbol . $orderPayRecordChange['pay'].'；';
                                    break;
                                default:
                                    if ($orderPayRecordChange['hotelpay_id'] == 0) {
                                        $detail .= '改为[其他消费--'.$otherCostInfo[$orderPayRecordChange['type']]['name'].' '.$orderPayRecordChange['name'].']'. $symbol . $orderPayRecordChange['pay'].'；';
                                    } else {
                                        $detail .= '改为[其他消费--'.$otherCostInfo[$orderPayRecordChange['type']]['name'].' '.$hotelPayInfo[$orderPayRecordChange['hotelpay_id']]['name'] . ']收款' . $symbol . $orderPayRecordChange['pay'] . ';';
                                    }
                                    break;
                            }
                            $detail .= '\n';
                        }
                        unset($orderPayRecordChange);
                        break;
                }
                $onceChange['z'] = $detail;
            }

            // 查房信息变化
            if ($change['check']) {
                $detail = '';
                switch (LANG_SET) {
                    case 'en_us':
                        foreach ($change['checkChange'] as $index => $checkChange) {
                            switch ($checkChange['type']) {
                                case ORDER_CHANGE_ADD:
                                    $detail .= 'The task of checking rooms has been assigned. ';
                                    break;
                                case ORDER_CHANGE_EDIT:
                                    $detail .= 'The room has been checked.\n';
                                    $costString = '';
                                    $changeCostString = '';
                                    if (!empty($checkChange['hotelroomcost_id'])) {
                                        $hotelRoomCostIds = explode(',', $checkChange['hotelroomcost_id']);
                                        foreach ($hotelRoomCostIds as $key => $costId) {
                                            $costString .= $hotelRoomCostData[$costId]['name'] . '、';
                                        }
                                        unset($costId);
                                    }

                                    if (!empty($checkChange['hotelroomcost_id_before'])) {
                                        $hotelRoomCostIdsBefore = explode(',', $checkChange['hotelroomcost_id_before']);
                                        foreach ($hotelRoomCostIdsBefore as $key => $costId) {
                                            $changeCostString .= $hotelRoomCostData[$costId]['name'] . ' ';
                                        }
                                        unset($costId);
                                    }

                                    if (!empty($costString) && !empty($changeCostString)) {
                                        $detail .= 'Consumer goods: ' . $costString . 'Changed to: ' . $changeCostString . '\n';
                                    } else if (!empty($costString)) {
                                        $detail .= 'Consumer goods: ' . $costString . '\n';
                                    } else {
                                        $detail .= '';
                                    }

                                    if (!empty($checkChange['remark']) && !empty($checkChange['remark_before'])) {
                                        $detail .= 'Note: ' . $checkChange['remark_before'] . '. Changed to: '. $checkChange['remark'] . '.';
                                    } else if (!empty($checkChange['remark'])) {
                                        $detail .= 'Note: ' . $checkChange['remark'] . '。';
                                    } else {
                                        $detail .= '';
                                    }

                                    break;
                            }
                            $detail .= '\n';
                        }
                        break;
                    case 'zh_tw':
                        foreach ($change['checkChange'] as $index => $checkChange) {
                            switch ($checkChange['type']) {
                                case ORDER_CHANGE_ADD:
                                    $detail .= '發送查房任務;';
                                    break;
                                case ORDER_CHANGE_EDIT:
                                    $detail .= '查房完畢。\n';
                                    $costString = '';
                                    $changeCostString = '';
                                    if (!empty($checkChange['hotelroomcost_id'])) {
                                        $hotelRoomCostIds = explode(',', $checkChange['hotelroomcost_id']);
                                        foreach ($hotelRoomCostIds as $key => $costId) {
                                            $costString .= $hotelRoomCostData[$costId]['name'] . '、';
                                        }
                                        unset($costId);
                                    }

                                    if (!empty($checkChange['hotelroomcost_id_before'])) {
                                        $hotelRoomCostIdsBefore = explode(',', $checkChange['hotelroomcost_id_before']);
                                        foreach ($hotelRoomCostIdsBefore as $key => $costId) {
                                            $changeCostString .= $hotelRoomCostData[$costId]['name'] . '、';
                                        }
                                        unset($costId);
                                    }

                                    if (!empty($costString) && !empty($changeCostString)) {
                                        $detail .= '消费物品：' . $costString . ' 改為：' . $changeCostString . '\n';
                                    } else if (!empty($costString)) {
                                        $detail .= '消费物品：' . $costString . '\n';
                                    } else {
                                        $detail .= '';
                                    }

                                    if (!empty($checkChange['remark']) && !empty($checkChange['remark_before'])) {
                                        $detail .= '備註：' . $checkChange['remark_before'] . '。 改為：'. $checkChange['remark'] . '。';
                                    } else if (!empty($checkChange['remark'])) {
                                        $detail .= '備註：' . $checkChange['remark'] . '。';
                                    } else {
                                        $detail .= '';
                                    }

                                    break;
                            }
                            $detail .= '\n';
                        }
                        break;
                    default:
                        foreach ($change['checkChange'] as $index => $checkChange) {
                            switch ($checkChange['type']) {
                                case ORDER_CHANGE_ADD:
                                    $detail .= '发送查房任务;';
                                    break;
                                case ORDER_CHANGE_EDIT:
                                    $detail .= '查房完毕。\n';
                                    $costString = '';
                                    $changeCostString = '';
                                    if (!empty($checkChange['hotelroomcost_id'])) {
                                        $hotelRoomCostIds = explode(',', $checkChange['hotelroomcost_id']);
                                        foreach ($hotelRoomCostIds as $key => $costId) {
                                            $costString .= $hotelRoomCostData[$costId]['name'] . '、';
                                        }
                                        unset($costId);
                                    }

                                    if (!empty($checkChange['hotelroomcost_id_before'])) {
                                        $hotelRoomCostIdsBefore = explode(',', $checkChange['hotelroomcost_id_before']);
                                        foreach ($hotelRoomCostIdsBefore as $key => $costId) {
                                            $changeCostString .= $hotelRoomCostData[$costId]['name'] . '、';
                                        }
                                        unset($costId);
                                    }

                                    if (!empty($costString) && !empty($changeCostString)) {
                                        $detail .= '消费物品：' . $costString . ' 改为：' . $changeCostString . '\n';
                                    } else if (!empty($costString)) {
                                        $detail .= '消费物品：' . $costString . '\n';
                                    } else {
                                        $detail .= '';
                                    }

                                    if (!empty($checkChange['remark']) && !empty($checkChange['remark_before'])) {
                                        $detail .= '备注：' . $checkChange['remark_before'] . '。 改为：'. $checkChange['remark'] . '。';
                                    } else if (!empty($checkChange['remark'])) {
                                        $detail .= '备注：' . $checkChange['remark'] . '。';
                                    } else {
                                        $detail .= '';
                                    }

                                    break;
                            }
                            $detail .= '\n';
                        }
                        break;
                }
                $onceChange['c'] = $detail;
            }

            array_push($output, $onceChange);
        }
        return $output;
    }

    /**
     * 添加订单||检查房间ID、检查房间是否可预定、判断用户是否注册、检查订单状态(如果有金额，状态改为以支付状态，)、添加订单数据、添加订单房间数据、添加用户房间数据、添加操作历史
     * //添加todo（补录订单startDate < 今天） //传递数据 新旧数据、状态
     * @modify songanwei 2016-01-05
     * @modify trainyao 2016-01-18      增加录入订单后写入数据到redis
     * @modify trainyao  2016-04-11     提前获取房卡
     * @modify trainyao   2016-05-09    添加多事务模式
     * @modify trainyao   2016-08-26    添加同住人,改变orderDetails参数格式
     * @modify zhangzhen   2017-03-01    增加会员
     * @modify zhangzhen   2017-06-05    增加钟点房
     * @param integer $hotelId  客栈ID
     * @param integer $hotelChannelId 渠道ID
     * @param integer $deposit 押金
     * @param integer $payment 应付金额
     * @param integer $receipt 已收金额
     * @param strig $remark 备注
     * @param array $orderDetails  子订单详细信息 [{roomId, orderDate, nights, payment, users: [{name, mobile, identity}, {}, {}, ...], ,  
     *                                             }, {}, {},...]
     * @param array $receives  收款方式
     * @param integer $type 状态类型
     * @param integer $recordForm 操作来源
     * @param mixin $multiTransMode  是否在事务嵌套模式内
     * @param integer $checkIn  直接入住时 检查该房间当天之前已预订或已入住的房间信息 1：检查 0：不检查
     * @param integer $orderBookUser 微预定用户id    当操作来源于微预定 订单操作者为微预定用户
     * @param array $vip  vip打折信息
     * @param array $minusInfo  立减优惠信息
     * @param array $minusPrice  立减优惠信息
     * @param string $version  移动端版本
     * @param array $vipCard 会员卡信息
     */
    public function addInfo($hotelId, $hotelChannelId, $deposit, $payment, $receipt, $remark, $orderDetails, $receives, $type, $recordFrom = 0, $mutilTransMode = false, $checkIn = 0, $orderBookUser = 0, $vip = null, $minusInfo = null, $minusPrice = null, $version = null, $vipCard = null) {

        // 检查是否有房间权限限制
        if (MODULE_NAME != 'Extend') {
            $adminId = getUserId();
            $adminAuthorityLogic = A('Common/AdminAuthority', 'Logic');
            if (!$adminAuthorityLogic->checkIsAdmin($adminId, $hotelId)) {
                $accountLogic = A('Common/Account', 'Logic');
                $roomAuthority = $accountLogic->getAdminRoomAuthority($adminId, $hotelId);

                // 判断前端传来的房间ID是否都有权限
                if (!empty(array_diff(array_column($orderDetails, 'roomId'), $roomAuthority))) {
                    throw new \Exception('403,202', 202);
                }
            }
        }
        $roomInfoModel = D('RoomInfo');
        $roomTypeModel = D('RoomType');
        $hotelChannelModel = D('HotelChannel');
        $hotelChannel = $hotelChannelModel->getInfo($hotelChannelId);
        if (!$hotelChannel || ($hotelChannel['hotelentity_id'] != $hotelId)) {
            throw new \Exception('403,202', 202);
        }
        //检查客栈是否启用
        $hotelLogic = A('Common/Hotel', 'Logic');
        //检查客栈是否有效
        $hotelLogic->checkHotelActive($hotelId);
        $hotelLogic->checkHotelStatus($hotelId);

        $timeArray = $this->prepareCheckTimeCross($hotelId, $orderDetails);
        // 检查参数时间冲突
        $this->checkTimeCross($orderDetails, $timeArray);
        // 获取客栈最迟退房时间 
        if (isset($orderDetails[0]['hour']) && $orderDetails[0]['hour'] > 0) {
            //第一个入住人有hour 就代表钟点房 保存钟点房的type
            $this->checkRoomType($orderDetails,$hotelId,1);
            $checkinType = 1;
        } elseif (isset($orderDetails[0]['month']) && $orderDetails[0]['month'] > 0) {
            //长租房与间夜房一样
            $this->checkRoomType($orderDetails,$hotelId,2);
            $checkinType = 0;

        } else {
            //间夜房
            $checkinType = 0;
        }
        $hotelBookDetail = $hotelLogic->getHotelBookingDetail($hotelId, $checkinType);
        $hotelCheckoutTime = isset($hotelBookDetail['checkouttime']) ? $hotelBookDetail['checkouttime'] : '12:00';
        $hotelCheckinTime = isset($hotelBookDetail['checkintime']) ? $hotelBookDetail['checkintime'] : '14:00';
        // 预定(直接入住)分割时间 范围 00:00 - 06:00
        $hotelOrderDiffTime = isset($hotelBookDetail['splitordertime']) ? $hotelBookDetail['splitordertime'] : '00:00';
        $userLoginLogic = A('Common/UserLogin', 'Logic');

         // 维修房数据
        $roomServiceModel = D('RoomService');
        $allRoomIds = array_column($orderDetails, 'roomId');
        $roomServiceList = $roomServiceModel->getServiceListByRoomId($allRoomIds, true);
        $roomServiceList = getArrayValueAsIndex($roomServiceList, 'roominfo_id');

        $roomIds = array();
        $preTimeArray = array();
        //添加订单房间数据
        $subOrderToAdd = array();
        $creater = getUserId();
        $newStatus = (double) $receipt > 0 ? ORDER_PAYED : ORDER_BOOKED;
        $currentHour = date('H:i');
        $today = date('Y-m-d');
        // 插入更新
        foreach ($orderDetails as &$orderDetailExt) {
            $roomId = $orderDetailExt['roomId'];
            $roomInfo = $roomInfoModel->getInfo($roomId);
            if (!$roomInfo || ($roomInfo['hotelentity_id'] != $hotelId)) {
                throw new \Exception('403,301', 301);
            }
            //赋值房间号、房型
            $roomType = $roomTypeModel->getInfo($roomInfo['roomtype_id']);
            $orderDetailExt['roomName'] = $roomInfo['name'];
            $orderDetailExt['roomType'] = $roomType['name'];
            $orderDetailExt['roomFrom'] = $roomInfo['roomfrom'];
            $orderDetailExt['startdate'] = getOrderStartTime($orderDetailExt['orderDate']);
            // 检查当天之前是否有订单
            $isExistOrderRoom = ValidateCheckIn($hotelId, $roomId, '', $orderDetailExt['orderDate']);
            $ismidnightorder = 0;
            if ($today == $orderDetailExt['orderDate'] && '00:00' < $currentHour && $currentHour < $hotelOrderDiffTime && empty($isExistOrderRoom)) {
                $hotelOrderDiffTimeType = 1;
                $ismidnightorder = 1;
                // 在凌晨00:00 至 预定(直接入住)分割时间 之间预定需要从新算结束时间 （预定(直接入住)分割时间 到 最迟退房时间 算一天 列：2017-11-02 + $hotelOrderDiffTime - 2017-11-02 + $hotelCheckinTime 算一天）
                if ($orderDetailExt['nights'] == 1) {
                    $orderDetailExt['enddate'] = $orderDetailExt['orderDate'] . " 00:00:00";
                } else {
                    $orderDetailExt['enddate'] = getOrderEndTime($orderDetailExt['orderDate'], $orderDetailExt['nights'] - 1, $orderDetailExt['hour']);
                }
            } else {
                $hotelOrderDiffTimeType = 0;
                $orderDetailExt['enddate'] = getOrderEndTime($orderDetailExt['orderDate'], $orderDetailExt['nights'], $orderDetailExt['hour']);
            }
            // 获取订单状态
            $orderDetailExt['status'] = $this->getOrderStatus($orderDetailExt['startdate'], $orderDetailExt['enddate'], $type, $newStatus, $hotelCheckoutTime, $checkinType, $hotelOrderDiffTimeType);
            // 预定端预定订单状态为已过期
            $orderDetailExt['status']  = in_array($recordFrom, array(ORDER_CHANGE_BOOK_WEB)) ? ORDER_OUTDATED : $orderDetailExt['status'];
            // 检查用户是否已注册
            foreach ($orderDetailExt['users'] as &$orderDetailUserItem) {
                if ($orderDetailUserItem['mobile']) {
                    $userId = $userLoginLogic->checkRegister($orderDetailUserItem['mobile'], false, $orderDetailUserItem['areacode']);
                    if ($userId) {
                        $orderDetailUserItem['userlogin_id'] = $userId;
                    } else {
                        $orderDetailUserItem['userlogin_id'] = 0;
                    }
                } else {
                    $orderDetailUserItem['userlogin_id'] = 0;
                }
            }
            unset($orderDetailUserItem);
            /*if (in_array($orderDetailExt['roomId'], $roomIds)) {
                throw new \Exception('403,500', 500);
            }*/
            // 检查参数时间冲突
            $startTimeIndex = strtotime($orderDetailExt['startdate']);
            $endTimeIndex = strtotime($orderDetailExt['enddate']);
            $preTimeArray[$startTimeIndex] = ['end' => $endTimeIndex];
            $checkRestul = $this->bookCheckTimeCross($preTimeArray, $startTimeIndex, $endTimeIndex);
            if ($checkRestul === false) {
                throw new \Exception('403,500', 500);
            }

            // 检查时间段内是否是维修房
            if (isset($roomServiceList[$roomId])) {
                $roomServiceStartDate = date('Y-m-d', $roomServiceList[$roomId]['startdate']);
                $roomServiceEndDate = date('Y-m-d', $roomServiceList[$roomId]['enddate']);
                $roomServiceDateArray = getDatesBetweenTime($roomServiceStartDate, $roomServiceEndDate, true);
                // 是否夜审订单 ismidnightorder=1
                if ($ismidnightorder == 1) {
                    $orderDateArray = getDatesBetweenTime($orderDetailExt['startdate'], $orderDetailExt['enddate'], true);
                } else {
                    $orderDateArray = getDatesBetweenTime($orderDetailExt['startdate'], $orderDetailExt['enddate']);
                }
                if (!empty(array_intersect($roomServiceDateArray, $orderDateArray))) {
                    throw new \Exception('403,514', 514);
                }
            }
            //检测脏房所需房间号
            array_push($roomIds, $orderDetailExt['roomId']);
            //待添加的子订单数据
            array_push($subOrderToAdd, array(
                'roominfo_id' => $orderDetailExt['roomId'],
                'creator' => $creater,
                'hour' => isset($orderDetailExt['hour']) ? $orderDetailExt['hour'] : 0,
                'month' => isset($orderDetailExt['month']) ? $orderDetailExt['month'] : 0,
                'night' => $orderDetailExt['nights'],
                'realnight' => $orderDetailExt['nights'],
                'startdate' => $orderDetailExt['startdate'],
                'enddate' => $orderDetailExt['enddate'],
                'checkindate' => date('Y-m-d H:i:s'),
                'checkoutdate' => $orderDetailExt['enddate'],
                'roomtype_name' => $orderDetailExt['roomType'],
                'roominfo_name' => $orderDetailExt['roomName'],
                'roominfo_from' => $orderDetailExt['roomFrom'],
                'payment' => $orderDetailExt['payment'],
                'status' => $orderDetailExt['status'],
                'ismidnightorder' => $ismidnightorder,
                'minusprice' => !is_null($minusPrice) ? $minusPrice : 0,
            ));
        }
        unset($orderDetailExt);
        
        // 直接入住时 获取该房间当天之前已预订或已入住的房间信息
        // 获取脏房信息
        if ($type == 2 && $checkIn == 1) {
            //不做任何插入或更新 
            $roomData = ValidateCheckIn($hotelId,$roomIds);
            return $roomData;
        }

        //添加数据
        $orderInfoModel = D('OrderInfo');
        $commit = true;

        // 操作者
        $userId = $recordFrom == ORDER_CHANGE_BOOK_WEB ? $orderBookUser : $userId;
        //获取第一个入住人为预订人
        $mobile = $orderDetails[0]['users'][0]['mobile'] ? $orderDetails[0]['users'][0]['mobile'] : '';
        $areaCode = $orderDetails[0]['users'][0]['areacode'] ? $orderDetails[0]['users'][0]['areacode'] : '86';
        $identity = $orderDetails[0]['users'][0]['identity'] ? $orderDetails[0]['users'][0]['identity'] : '';
        $realName = $orderDetails[0]['users'][0]['name'];
        $orderUserLoginId = $orderDetails[0]['users'][0]['userlogin_id'];

        $orderId = null;
        $orderRecordId = null;

        //开启事务
        if ($mutilTransMode === false) {
            $orderInfoModel->startTrans();
        }
        //添加操作历史记录
        if ($commit) {
            $orderRecordModel = D('OrderRecord');
            $result = $orderRecordId = $orderRecordModel->addInfo(0, $recordFrom, $payment, 1, 1, 1, $recordFrom == ORDER_CHANGE_BOOK_WEB ? $userId : null);
            if ($result == false) {
                $commit = false;
            }
        }

        if (!empty($minusInfo)) {
            $truePayment = isset($minusInfo['orig']) ? $minusInfo['orig'] : $payment;
        } else {
            $truePayment = $payment;
        }

        // 保存父订单变化
        if ($commit) {
            $result = $this->saveOrderInfoChange($hotelId, null, $orderRecordId, $hotelChannelId, $deposit, $payment, $receipt, $orderUserLoginId, array(
                'hotelchannel_id' => $hotelChannelId,
                'remark' => $remark,
                'areacode' => $areaCode,
                'mobile' => $mobile,
                'name' => $realName,
                'identity' => $identity,
                'hotelchannel_before' => 0,
                'remark_before' => '',
                'areacode_before' => '',
                'mobile_before' => '',
                'name_before' => '',
                'identity_before' => '',
                'status' => $subOrderToAdd[0]['status'],
                'orig' => isset($vip['orig']) ? $vip['orig'] : $truePayment,
                'discount' => isset($vip['discount']) ? $vip['discount'] : 0,
                'discountrule' => isset($vip['discountRule']) ? $vip['discountRule'] : 0,
            ));
            if (empty($result)) {
                $commit = false;
            } else {
                $orderId = $result;
            }
        }


        // 保存父订单ID
        if ($commit) {
            $result = $orderRecordModel->saveOrder($orderRecordId, $orderId);
            if (empty($result)) {
                $commit = false;
            }
        }

        // 增加子订单
        $subOrderAddAllId = null;
        if ($commit) {
            $result = $this->changeSubOrder($hotelId, $orderId, $orderRecordId, $subOrderToAdd, null, null);
            if (empty($result)) {
                $commit = false;
            } else {
                $subOrderAddAllId = $result;
                $orderRoomIdCounter = $subOrderAddAllId;
                foreach ($subOrderToAdd as &$subOrderToAddItem) {
                    $subOrderToAddItem['id'] = $orderRoomIdCounter;
                    $subOrderToAddItem['hotelentity_id'] = $hotelId;
                    $subOrderToAddItem['orderinfo_id'] = $orderId;
                    $orderRoomIdCounter++;
                }
                unset($subOrderToAddItem);
            }
        }

        //钟点房不能提前拿卡
        if ($checkinType === 0) {
            // 处理插入的订单,找出能提前入住的子订单的index
            $orderDetailsCanPreGetCardIndex = array();
            // 在酒店入住时间前办理才进行查询 
            $needPreGetCard = date('H') < substr($hotelCheckinTime, 0, 2) ? true : false;
            if ($type == 2 && $needPreGetCard) {
                $needCheckCanPreGetCardSubOrders = array();
                foreach ($orderDetails as $orderDetail) {
                    array_push($needCheckCanPreGetCardSubOrders, array(
                        'roomId' => $orderDetail['roomId'],
                        'startdate' => $orderDetail['startdate'],
                        'enddate' => $orderDetail['enddate'],
                        'orderRoomId' => 0,
                    ));
                }
                unset($orderDetail);
                $orderDetailsCanPreGetCardIndex = $this->getCanPreGetCardIndex($hotelId, $needCheckCanPreGetCardSubOrders);
            }
        }

        //添加用户房间数据
        $orderRoomCards = array();
        $orderUserToAdd = array();
        if ($commit) {
            $orderRoomIndex = $subOrderAddAllId;
            $currentCheckinTime = date('H:i:s');
            $todayDate = date('Y-m-d');

            // 直接入住或者补录订单的话,处理发房卡数据
            foreach ($orderDetails as $index => $orderDetail) {
                $startDateCheckinTime = $hotelCheckinTime;
                if (($type == 2 || $type == 3) && $checkinType === 0) {
                    $pushCard = true;
                    if ($orderDetail['orderDate'] == $todayDate || substr($orderDetail['enddate'], 0, 10) == $todayDate) {
                        // 查找是否可以提前入住
                        $canPreGetCard =  in_array($index, $orderDetailsCanPreGetCardIndex) ? true : false;
                        $canPreGetCard = $canPreGetCard && $needPreGetCard;
                        if ($type == 3) {
                            if ($orderDetail['status'] == ORDER_CHECKINED) {
                                $startDateCheckinTime = $hotelCheckinTime;
                            } else {
                                // 不是已入住状态的订单,不用处理
                                $pushCard = false;
                            }
                        } else {
                            $startDateCheckinTime = $canPreGetCard ? $currentCheckinTime : $hotelCheckinTime;
                        }
                        if ($pushCard) {
                            foreach ($orderDetail['users'] as $orderDetailUserItem) {
                                $orderRoomCards[] = array(
                                    'orderRoomId' => $orderRoomIndex,
                                    'name' => $orderDetailUserItem['name'],
                                    'areacode' => $orderDetailUserItem['areacode'] ? $orderDetailUserItem['areacode'] : '86',
                                    'mobile' => $orderDetailUserItem['mobile'] ? $orderDetailUserItem['mobile'] : '',
                                    'roomName' => $orderDetail['roomName'],
                                    'startdate' => substr($orderDetail['startdate'], 0, 11) . $startDateCheckinTime,
                                    'enddate' => substr($orderDetail['enddate'], 0, 11) . $hotelCheckoutTime,
                                );
                            }
                            unset($orderDetailUserItem);
                        }
                    }
                //钟点房按规定时间发卡
                } elseif($type == 2 && $checkinType === 1) {
                    foreach ($orderDetail['users'] as $orderDetailUserItem) {
                        $orderRoomCards[] = array(
                            'orderRoomId' => $orderRoomIndex,
                            'name' => $orderDetailUserItem['name'],
                            'areacode' => $orderDetailUserItem['areacode'] ? $orderDetailUserItem['areacode'] : '86',
                            'mobile' => $orderDetailUserItem['mobile'] ? $orderDetailUserItem['mobile'] : '',
                            'roomName' => $orderDetail['roomName'],
                            'startdate' => $orderDetail['startdate'],
                            'enddate' => $orderDetail['enddate'],
                        );
                    }
                    unset($orderDetailUserItem);
                }

                // 保存userRoom数据
                $orderUserToAdd[$index] = array();
                if ($checkinType === 0) {
                    foreach ($orderDetail['users'] as $orderDetailUserItem) {
                        array_push($orderUserToAdd[$index], array(
                            'userlogin_id' => $orderDetailUserItem['userlogin_id'],
                            'roominfo_id' => $orderDetail['roomId'],
                            'startdate' => substr($orderDetail['startdate'], 0, 11) . $startDateCheckinTime,
                            'enddate' => substr($orderDetail['enddate'], 0, 11) . $hotelCheckoutTime,
                            'name' => $orderDetailUserItem['name'],
                            'areacode' => $orderDetailUserItem['areacode'] ? $orderDetailUserItem['areacode'] : '86',
                            'mobile' => $orderDetailUserItem['mobile'] ? $orderDetailUserItem['mobile'] : '',
                            'identity' => $orderDetailUserItem['identity'] ? $orderDetailUserItem['identity'] : '',
                            'idsex' => $orderDetailUserItem['idsex'] ? $orderDetailUserItem['idsex'] : '',
                            'idnation' => $orderDetailUserItem['idnation'] ? $orderDetailUserItem['idnation'] : '',
                            'idaddress' => $orderDetailUserItem['idaddress'] ? $orderDetailUserItem['idaddress'] : '',
                            'isdelete' => $orderDetail['status'] == ORDER_CHECKOUTED ? IS_DELETE : NOT_DELETE,
                        ));
                    }
                } else {
                    foreach ($orderDetail['users'] as $orderDetailUserItem) {
                        array_push($orderUserToAdd[$index], array(
                            'userlogin_id' => $orderDetailUserItem['userlogin_id'],
                            'roominfo_id' => $orderDetail['roomId'],
                            'startdate' => $orderDetail['startdate'],
                            'enddate' => $orderDetail['enddate'],
                            'name' => $orderDetailUserItem['name'],
                            'areacode' => $orderDetailUserItem['areacode'] ? $orderDetailUserItem['areacode'] : '86',
                            'mobile' => $orderDetailUserItem['mobile'] ? $orderDetailUserItem['mobile'] : '',
                            'identity' => $orderDetailUserItem['identity'] ? $orderDetailUserItem['identity'] : '',
                            'idsex' => $orderDetailUserItem['idsex'] ? $orderDetailUserItem['idsex'] : '',
                            'idnation' => $orderDetailUserItem['idnation'] ? $orderDetailUserItem['idnation'] : '',
                            'idaddress' => $orderDetailUserItem['idaddress'] ? $orderDetailUserItem['idaddress'] : '',
                            'isdelete' => $orderDetail['status'] == ORDER_CHECKOUTED ? IS_DELETE : NOT_DELETE,
                        ));
                    }
                }
                unset($orderDetailUserItem);
                $orderRoomIndex++;
            }
            unset($orderDetail);
        }

        // 添加订单用户数据信息
        if ($commit && $orderDetails) {
            $result = $this->saveOrderUserChange($hotelId, $orderId, $orderRecordId, array(
                'orderroom_id' => $subOrderAddAllId,
                'data' => $orderUserToAdd,
            ), null, null);
            if (empty($result)) {
                $commit = false;
            }
        }

        // 如有会员卡消费 则修改会员卡
        if ($commit && $receives && !empty($vipCard)) {
            $result = $this->modifyVipUserCard($hotelId, $vipCard['cardMobile'], $vipCard['cardAreaCode'], $receives);
            if ($result == false) {
                $commit = false;
            }
            $vipUserModel = D('VipUser');
            $vipUserInfo = $vipUserModel->getInfoByMobile($hotelId, $vipCard['cardMobile'], $vipCard['cardAreaCode']);
            $vipUserId = $vipUserInfo['id'];
        }

        //添加订单支付记录数据
        if ($commit && $receives) {
            $receiptArray = array();
            $depositArray = array();
            foreach ($receives as $receive) {
                if ($receive['category'] == PAY_CHANGE_RECEIPT) {
                    array_push($receiptArray, array(
                        'pay' => $receive['value'],
                        'id' => $receive['type'],
                        'transBeforeValue' => $receive['transBeforeValue'],
                        'currencyId' => $receive['transCurrencyId'],
                    ));
                } else if ($receive['category'] == PAY_CHANGE_DEPOSIT) {
                    array_push($depositArray, array(
                        'pay' => $receive['value'],
                        'id' => $receive['type'],
                        'transBeforeValue' => $receive['transBeforeValue'],
                        'currencyId' => $receive['transCurrencyId'],
                    ));
                } else {
                    // 其他消费 (包含其他消费代收)
                    array_push($receiptArray, array(
                        'pay' => $receive['value'],
                        'id' => $receive['type'],
                        'category' => $receive['category'],
                        'transBeforeValue' => $receive['transBeforeValue'],
                        'currencyId' => $receive['transCurrencyId'],
                    ));
                }
            }
            unset($receive); 

            $vipUserId = isset($vipUserId) ? $vipUserId : '0';
            $result = $this->saveOrderPayChange($hotelId, $orderId, $orderRecordId, $receiptArray, $depositArray, null, $vipUserId);
            if ($result == false) {
                $commit = false;
            }
        }

        // 添加数据到redis
        $returnData = array();
        if ($commit) {
            $orderRoomIdIndex = $subOrderAddAllId;
            //返回的数据
            foreach ($orderDetails as $orderDetail) {
                $startDate = date("Y-m-d", strtotime(getOrderStartTime($orderDetail['orderDate'])));
                // 在凌晨00:00 至 预定(直接入住)分割时间 之间预定需要从新算结束时间 （预定(直接入住)分割时间 到 最迟退房时间 算一天 列：2017-11-02 + $hotelOrderDiffTime - 2017-11-02 + $hotelCheckinTime 算一天）
                if ($today == $startDate && '00:00' < $currentHour && $currentHour < $hotelOrderDiffTime) {
                    if ($orderDetail['nights'] == 1) {
                        $endDate = $startDate;
                    } else {
                        $endDate = date("Y-m-d", strtotime(getOrderEndTime($startDate, $orderDetail['nights'] - 1)));
                    }
                } else {
                    $endDate = date("Y-m-d", strtotime(getOrderEndTime($startDate, $orderDetail['nights'])));
                }

                $status = $orderDetail['status'];
                // 选择语言
                switch (LANG_SET) {
                    case 'zh_cn':
                        $hotelChannel['name'] = explode('/', $hotelChannel['name'])[0];
                        break;
                    case 'en_us':
                        $hotelChannel['name'] = explode('/', $hotelChannel['name'])[1];
                        break;
                    case 'zh_tw':
                        $hotelChannel['name'] = explode('/', $hotelChannel['name'])[2];
                        break;
                    default:
                        $hotelChannel['name'] = explode('/', $hotelChannel['name'])[0];
                        break;
                }

                // 修改该退房而未退房的子订单状态  status = 6
                if (!is_null($version)) {
                    if ($version >= '2.0.17') {
                        $returnDataItem = $this->modifyOrderRoomStatus([array(
                                'hotelentity_id' => $hotelId,
                                'status' => $status,
                                'hour' => isset($orderDetail['hour']) ? $orderDetail['hour'] : 0,
                                'enddate' => isset($orderDetail['hour']) ? $orderDetail['enddate'] : $endDate,
                            )]
                        );
                        $status = $returnDataItem[0]['status'];
                    }
                } else {
                    $returnDataItem = $this->modifyOrderRoomStatus([array(
                            'hotelentity_id' => $hotelId,
                            'status' => $status,
                            'hour' => isset($orderDetail['hour']) ? $orderDetail['hour'] : 0,
                            'enddate' => isset($orderDetail['hour']) ? $orderDetail['enddate'] : $endDate,
                        )]
                    );
                    $status = $returnDataItem[0]['status'];
                }

                $returnDataItem = array(
                    'id' => $orderRoomIdIndex,
                    'status' => $status,
                    'statusName' => $this->statusMap[LANG_SET][$status],
                    'night' => $orderDetail['nights'],
                    'hour' => isset($orderDetail['hour']) ? $orderDetail['hour'] : 0,
                    'month' => isset($orderDetail['month']) ? $orderDetail['month'] : 0,
                    'order' => $orderId,
                    'room' => $orderDetail['roomId'],
                    'start' => $startDate,
                    'starttime' => $orderDetail['orderDate'],
                    'end' => $endDate,
                    'endDate' => $endDate,
                    'pay' => $orderDetail['payment'],
                    'roomtype' => $orderDetail['roomType'],
                    'roomname' => $orderDetail['roomName'],
                    'name' => $realName,
                    'areaCode' => $areaCode,
                    'mobile' => $mobile,
                    'identity' => $identity,
                    'deposit' => $deposit,
                    'receipt' => $receipt,
                    'price' => $payment,
                    'remark' => $remark,
                    'channelname' => $hotelChannel['name']
                );
                array_push($returnData, $returnDataItem);
                // TODO 订单自动提示,先不做
                // $orderRoomModel->addInfoInRedis($hotelId, $orderRoomIdIndex, $returnDataItem);
                $orderRoomIdIndex++;
            }
        }
        
        //同时将发生变化数据丢到消息队列
        if ($subOrderToAdd) {
            $result = $this->pushBackendTask($this->backendTaskType['ADD'], NULL, $subOrderToAdd);
            if (!$result) {
                $commit = false;
            }
        }
        //事务提交回滚
        if ($commit) {
            if ($mutilTransMode === false) {
                $orderInfoModel->commit();
            }
            //直接入住发送短信通知
            if (($type == 2 || $type == 3) && $orderRoomCards) {
                $this->pushBackendCardTask($this->backendTaskType['ADD'], $hotelId, null, $orderRoomCards);
            }
            //返回必须数据
            return $returnData;
        } else {
            if ($mutilTransMode === false) {
                $orderInfoModel->rollback();
            }
            throw new \Exception('500,508', 508);
        }
    }

    /**
     * 修改订单
     * 方法会抛异常
     * TODO 已取消已过期限至不能修改日期、房间，已预订不用传 其他状态需要传入前后发生变化数据
     * @modify songanwei 2016-01-06
     * @modify trainyao  2016-04-11     提前获取房卡
     * @modify trainyao  2016-06-29     房间权限功能增加对应修改
     * @modify zhangzhen  2017-01-09     修复已入住的订单收款后变为已预订的BUG
     * @modify zhangzhen  2017-03-14     添加会员
     * @param integer $hotelId 客栈ID
     * @param integer $orderId 订单ID
     * @param integer $hotelChannelId 渠道ID
     * @param integer $deposit 押金
     * @param integer $receipt 已收金额
     * @param string $remark 备注
     * @param array $frontSubOrders 子订单详细信息 [{orderRoomId(子订单ID, 新增订单传0), roomId, orderDate, nights, users=>[{
     *                                                   mobile, name, identity, orderUser(orderUserId, 新增订单传0)
     *                                               }, {},...],}, {}, ...]
     * @param array $receives 收款方式
     * @param integer $recordFrom 订单来源 0= Web端 1= app端 2= 微预定
     * @param integer $operator 操作人id
     * @param bool|mixin $multiTransMode 是否在事务嵌套模式,默认不在
     * @param string $vip 打折信息
     * @param string $charityPrice 订单义卖价
     * @param array $orderPayRecord 收款记录
     * @param array $vipCard 会员卡信息
     * @param integer $couponGetNo 优惠券用户领取号
     * @return bool
     * @throws \Exception
     */
    public function saveInfo($hotelId, $orderId, $hotelChannelId, $deposit, $receipt, $remark, $frontSubOrders, $receives, $recordFrom, $operator = null, $multiTransMode = false, $vip = null, $charityPrice = null, $orderPayRecord = null, $vipCard = null, $couponGetNo = null) {
        // 获取订单详情
        try {
            $orderInfo = $this->getOrderInfo($hotelId, array($orderId), true, false);
        } catch (\Exception $e) {
            throw $e;
        }
        $orderInfo = $orderInfo[0];
        // 立减优惠订单 不能修改房型
        $roomIdAlls = array_column($frontSubOrders, 'roomId');
        if ($orderInfo['rooms'][0]['minusprice'] != '0.00') {
            $roomInfoModel = D('RoomInfo');
            // 第一个子订单的房型id
            $oldRoomDetail = $roomInfoModel->getInfo($orderInfo['rooms'][0]['roominfo_id']);
            $oldRoomTypeId = $oldRoomDetail['roomtype_id'];
            // 修改或新增的房型id
            if (count($roomIdAlls) == 1) {
                $editOrAddRoomDetail = $roomInfoModel->getInfo($roomIdAlls);
                if ($oldRoomTypeId != $editOrAddRoomDetail['roomtype_id']) {
                    throw new \Exception('403,316', 316);
                }
            } else {
                $editOrAddRoomDetail = $roomInfoModel->getInfo($roomIdAlls);
                foreach ($editOrAddRoomDetail as $key => $roomDetail) {
                    if ($oldRoomTypeId != $roomDetail['roomtype_id']) {
                        throw new \Exception('403,316', 316);
                    }
                }
                unset($roomDetail);
            }
        }

        // 维修房数据
        $roomServiceModel = D('RoomService');
        $roomServiceList = $roomServiceModel->getServiceListByRoomId($roomIdAlls, true);
        $roomServiceList = getArrayValueAsIndex($roomServiceList, 'roominfo_id');

        // 检查是否有房间权限限制,记录没有房间权限的子订单ID
        $noRoomRightOrderRoomId = array();
        if (MODULE_NAME != 'Extend') {
            $adminId = getUserId();
            $adminAuthorityLogic = A('Common/AdminAuthority', 'Logic');
            if (!$adminAuthorityLogic->checkIsAdmin($adminId, $hotelId)) {
                $accountLogic = A('Common/Account', 'Logic');
                $roomAuthority = $accountLogic->getAdminRoomAuthority($adminId, $hotelId);
                // 判断前端传来的房间ID是否都有权限
                if (!empty(array_diff(array_column($frontSubOrders, 'roomId'), $roomAuthority))) {
                    throw new \Exception('403,202', 202);
                }

                foreach ($orderInfo['rooms'] as $orderRoomItem) {
                    if (!in_array($orderRoomItem['roominfo_id'], $roomAuthority)) {
                        array_push($noRoomRightOrderRoomId, $orderRoomItem['id']);
                    }
                }
                unset($orderRoomItem);
            }
        }
        $checkinType = $orderInfo['rooms'][0]['hour'] >0 ? 1 : 0;
        if ($orderInfo['rooms'][0]['hour'] > 0) {
            $this->checkRoomType($hotelId, $frontSubOrders, 1);
        } elseif ($orderInfo['rooms'][0]['month'] > 0) {
            $this->checkRoomType($hotelId, $frontSubOrders, 2);
        }
        // 遍历订单详细信息数组,收集信息,格式化订单数据
        // 收集信息:统计过期子订单ID,获取redis订单,将有效已过期订单转为已预订
        // 收集信息:订单预定人信息
        // 已取消房间数
        $cancelRoomCount = 0;
        $outDateOrderRoomIds = array();
        $formattedFrontSubOrders = getArrayValueAsIndex($frontSubOrders, 'orderRoomId');
        foreach ($orderInfo['rooms'] as $index => &$subOrderItem) {
            // 收集信息
            if ($subOrderItem['status'] == ORDER_OUTDATED) {
                array_push($outDateOrderRoomIds, $subOrderItem['id']);
            }
            // 有效房间数
            if ($subOrderItem['status'] == ORDER_CANCELED) {
                $cancelRoomCount ++;
            }
            if ($index == 0) {
                // 找到第一个关联订单的第一个入住人,判断预定人变化
                $firstOrderRoomFirstOrderUser = getArrayValueAsIndex($formattedFrontSubOrders[$subOrderItem['id']]['users'], 'orderUser');

                $firstOrderRoomFirstOrderUser = $firstOrderRoomFirstOrderUser[$subOrderItem['user'][0]['orderuser_id']];
                $bookerUser = $firstOrderRoomFirstOrderUser['name'];
                $bookerAreaCode = !empty($firstOrderRoomFirstOrderUser['areacode']) ? $firstOrderRoomFirstOrderUser['areacode'] : '86';
                $bookerMobile = !empty($firstOrderRoomFirstOrderUser['mobile']) ? $firstOrderRoomFirstOrderUser['mobile'] : '';
                $bookerIdentity = !empty($firstOrderRoomFirstOrderUser['identity']) ? $firstOrderRoomFirstOrderUser['identity'] : '';
            }
            // 格式化数据
            $subOrderItem['user'] = getArrayValueAsIndex($subOrderItem['user'], 'orderuser_id');
        }
        unset($subOrderItem);
        $orderInfo['rooms'] = getArrayValueAsIndex($orderInfo['rooms'], 'id');

        // 获取redis订单,将有效已过期订单转为已预订
        if (!empty($outDateOrderRoomIds)) {
            $orderRoomModel = D('OrderRoom');
            $redisOrderRecordInfo = $orderRoomModel->getInfoInRedisByHotelRoomOrderRoom($hotelId, null, $outDateOrderRoomIds);
            if ($redisOrderRecordInfo === false) {
                // redis查询失败
                throw new \Exception('500,506', 506);
            }
            foreach ($redisOrderRecordInfo as $redisOrderRecordItem) {
                $orderInfo['rooms'][$redisOrderRecordItem['orderroom_id']]['status'] = ORDER_BOOKED;
            }
            unset($redisOrderRecordItem);
        }

        // 获取订单存在的状态
        $orderStatuses = array_values(array_unique(array_column($orderInfo['rooms'], 'status')));
        // 若全部都是已取消,已过期的订单,不允许修改除备注信息
        $orderCanEdit = true;
        $remarkNeedUpdate = true;
        if (empty(array_diff($orderStatuses, array(ORDER_CANCELED, ORDER_OUTDATED)))) {
            $orderCanEdit = false;
        }
        // 检查备注是否需要更新
        if ($remark == $orderInfo['remark']) {
            $remarkNeedUpdate = false;
        }
        if (!$orderCanEdit && !$remarkNeedUpdate) {
            return true;
        }

        // 支付记录修改数据
        $orderPayRecordEdit = array();
        // 支付记录修改变化数据
        $orderPayRecordChangeData = array();

        $orderInfoNeedEdit = 0;
        $orderInfoExceptRemarkNeedEdit = 0;
        $orderRoomNeedEdit = 0;
        $orderUserNeedEdit = 0;
        $orderPayNeedEdit = 0;
        //$orderOtherPayNeedEdit = 0;
        $orderPayRecordNeedEdit = 0;
        $operator = $recordFrom == ORDER_CHANGE_BOOK_WEB ? $operator : getUserId();
        $bookerUserLoginId = $orderInfo['userlogin_id'];
        if ($orderCanEdit) {
            // 获取客栈房间信息,处理备用
            $roomIds = array_column($frontSubOrders, 'roomId');
            $roomLogic = A('Common/Room', 'Logic');
            $roomInfo = $roomLogic->getRoom($hotelId, $roomIds, true);
            $roomInfo = getArrayValueAsIndex($roomInfo, 'id');

            // 获取客栈最迟入住退房时间
            $hotelLogic = A('Common/Hotel', 'Logic');
            // 获取客栈最迟退房时间
            $hotelBookDetail = $hotelLogic->getHotelBookingDetail($hotelId, $checkinType);
            $hotelCheckinTime = isset($hotelBookDetail['checkintime']) ? $hotelBookDetail['checkintime'] : '14:00';
            $hotelCheckoutTime = isset($hotelBookDetail['checkouttime']) ? $hotelBookDetail['checkouttime'] : '12:00';
            // 预定(直接入住)分割时间 范围 00:00 - 06:00
            $hotelOrderDiffTime = isset($hotelBookDetail['splitordertime']) ? $hotelBookDetail['splitordertime'] : '00:00';
            $currentCheckinTime = date('H:i:s');
            // 是否可以提前拿卡
            $canPreGetCard = (date('H') < substr($hotelCheckinTime, 0, 2)  && $checkinType === 0) ? true : false;
            // 算出总价
            $payment = 0.00;
            // 处理前端传过来的子订单信息,删除非法数据,添加后续逻辑需要用的字段
            foreach ($frontSubOrders as $index => &$frontSubOrderItem) {
                $orderRoomId = $frontSubOrderItem['orderRoomId'];
                $orderRoomInDb = isset($orderInfo['rooms'][$orderRoomId]) ? $orderInfo['rooms'][$orderRoomId] : null;
                if (empty($orderRoomInDb) && !empty($orderRoomId)) {
                    unset($frontSubOrders[$index]);
                    continue;
                }

                $frontSubOrderItem['startdate'] = getOrderStartTime($frontSubOrderItem['orderDate']);
                // 在凌晨00:00 至 预定(直接入住)分割时间 之间预定需要从新算结束时间 （即夜审订单）
                if (!is_null($orderRoomInDb) && $orderRoomInDb['ismidnightorder']) {
                    // 夜审订单不能修改日期
                    if (date('Y-m-d', strtotime($orderRoomInDb['startdate'])) != $frontSubOrderItem['orderDate']) {
                        throw new \Exception('403,513', 513);
                    }

                    $hotelOrderDiffTimeType = 1;
                    if ($frontSubOrderItem['nights'] == 1) {
                        $frontSubOrderItem['enddate'] = $frontSubOrderItem['orderDate'] . ' 00:00:00';
                    } else {
                        $frontSubOrderItem['enddate'] = getOrderEndTime($frontSubOrderItem['orderDate'], $frontSubOrderItem['nights'] - 1, $frontSubOrderItem['hour']);
                    }
                } else {
                    $hotelOrderDiffTimeType = 0;
                    $frontSubOrderItem['enddate'] = getOrderEndTime($frontSubOrderItem['orderDate'], $frontSubOrderItem['nights'], $frontSubOrderItem['hour']);
                }

                //$frontSubOrderItem['enddate'] = getOrderEndTime($frontSubOrderItem['orderDate'], $frontSubOrderItem['nights'], $frontSubOrderItem['hour']);

                // 为检查是否能入住准备的字段
                $frontSubOrderItem['arrayIndex'] = $index;

                if (!is_null($orderRoomInDb)) {
                    if (in_array($orderRoomInDb['status'], array(ORDER_OUTDATED, ORDER_CANCELED))) {
                        $frontSubOrderItem['pass'] = true;
                        // 已取消,已过期订单不允许修改
                        // 将前端传过来的房间价格忽略,读取db里面的
                        $frontSubOrderItem['payment'] = $orderRoomInDb['payment'];
                    }
                    if ($orderRoomInDb['realnight'] == 0 && $checkinType === 0) {
                        // 实住晚数为0的子订单,不进行校验
                        $frontSubOrderItem['pass'] = true;
                    }
                }
                $frontSubOrderItem['users'] = getArrayValueAsIndex($frontSubOrderItem['users'], 'orderUser', 'multi');

                if (!$frontSubOrderItem['pass']) {
                    $payment += (double)$frontSubOrderItem['payment'];
                }
            }
            unset($frontSubOrderItem);

            // 获取可提前入住订单
            $canPreGetCardIndex = array();
            if ($canPreGetCard) {
                $canPreGetCardIndex = $this->getCanPreGetCardIndex($hotelId, $frontSubOrders);
            }

            // 检查订单时间冲突
            $timeArray = $this->prepareCheckTimeCross($hotelId, $frontSubOrders);
            $timeNotCross = $this->checkTimeCross($frontSubOrders, $timeArray);
            if ($timeNotCross != true) {
                return false;
            }

            // 获取可提前入住订单索引,检查时间冲突,算出总价后,格式化前端传入数据
            $frontSubOrders = getArrayValueAsIndex($frontSubOrders, 'orderRoomId', 'multi');
            $userLoginLogic = A('Common/UserLogin', 'Logic');

            // 如果存在不可操作的房间的子订单(不为已取消已过期),总价加入子订单价格
            if (!empty($noRoomRightOrderRoomId)) {
                foreach ($noRoomRightOrderRoomId as $orderRoomId) {
                    if (!in_array($orderInfo['rooms'][$orderRoomId]['status'], array(ORDER_CANCELED, ORDER_OUTDATED))) {
                        $payment += (double)$orderInfo['rooms'][$orderRoomId]['payment'];
                    }
                }
                unset($orderRoomId);
            }
            $payment = $payment > 999999.99 ? 999999.99 : $payment;
            //$paymentChange = $payment - $orderInfo['payment'];
            $paymentChange = $payment - $orderInfo['orig'];
            $paymentChange = $paymentChange < -999999.99 ? -999999.99 : $paymentChange;
            $paymentChange = $paymentChange > 999999.99 ? 999999.99 : $paymentChange;
            $receiptNew = ($orderInfo['receipt'] + $receipt);
            $receiptNew = $receiptNew > 999999.99 ? 999999.99 : $receiptNew;
            $depositNew = ($orderInfo['deposit'] + $deposit);
            $depositNew = $depositNew > 999999.99 ? 999999.99 : $depositNew;
            // 比较是否需要更新父订单
            if ($orderInfo['hotelchannel_id'] != $hotelChannelId || $orderInfo['mobile'] != $bookerMobile || $orderInfo['name'] != $bookerUser || $orderInfo['identity'] != $bookerIdentity || $receiptNew != $orderInfo['receipt'] || $depositNew != $orderInfo['depositNew'] || $payment != $orderInfo['orig'] || $bookerAreaCode != $orderInfo['areacode']) {
                $orderInfoExceptRemarkNeedEdit = 1;
                if (($orderInfo['mobile'] != $bookerMobile)) {
                    if (!empty($bookerMobile)) {
                        $userloginId = $userLoginLogic->checkRegister($bookerMobile, false, $bookerAreaCode);
                        $bookerUserLoginId = $userloginId ? $userloginId : 0;
                    } else {
                        $bookerUserLoginId = 0;
                    }
                }
            }
            // 获取修改订单准备数据
            $subOrderJustPayed = false;
            if ($orderInfo['receipt'] == 0 && $receipt > 0) {
                $subOrderJustPayed = true;
            }
            $newStatus = $receiptNew > 0 ? ORDER_PAYED : ORDER_BOOKED;
            $today = date('Y-m-d H:i:s');
            $orderRoomToAdd = $orderRoomToEdit = $orderRoomToDelete = array();
            // 修改统计逻辑函数需要的数据存放
            $orderChangeTaskEditData = array();
            // 房卡后台服务需要的数据存放
            $addOrderCardTaskData = $editOrderCardTaskOldData = $editOrderCardTaskNewData = array();
            $orderUserToEdit = array();
            $orderUserToAdd = array(
                'orderroom_id' => 0,
                'data' => array(),
            );
            $orderUserToAddWhileEdit = array();
            $orderUserToDelete = array(
                'orderuser_id' => array(),
                'userroom_id' => array(),
                'data' => array(),
            );
            $orderReceiveChangeData = $orderDepositChangeData = $orderOtherReceiveChangeData = array();
            $discount = 0;
            $month = 0;
            // 比较新旧订单数据,得出增删改的订单数据
            foreach ($orderInfo['rooms'] as $subOrderItem) {
                $frontSubOrderItem = isset($frontSubOrders[$subOrderItem['id']]) ? $frontSubOrders[$subOrderItem['id']][0] : null;
                if ($subOrderItem['status'] == 3 && $subOrderItem['month']>0) {
                    if ($subOrderItem['ismidnightorder']) {
                        $frontSubOrderItem['enddate'] = getOrderEndTime($frontSubOrderItem['orderDate'], $frontSubOrderItem['realnight'] -1);
                    } else {
                        $frontSubOrderItem['enddate'] = getOrderEndTime($frontSubOrderItem['orderDate'], $frontSubOrderItem['realnight']);
                    }

                    //$frontSubOrderItem['enddate'] = getOrderEndTime($frontSubOrderItem['orderDate'], $frontSubOrderItem['realnight']);
                }
                // 传入订单不存在,判断为删除订单
                if (is_null($frontSubOrderItem)) {
                    // 已取消,已退房,已过期订单不能再取消
                    if (in_array($subOrderItem['status'], array(ORDER_CANCELED, ORDER_CHECKOUTED, ORDER_OUTDATED))) {
                        continue;
                    }

                    $orderRoomToDeleteItem = array(
                        'orderroom_id' => $subOrderItem['id'],
                        'startdate_before' => $subOrderItem['startdate'],
                        'enddate_before' => $subOrderItem['checkoutdate'],
                        'roomtype_name_before' => $subOrderItem['roomtype_name'],
                        'roominfo_name_before' => $subOrderItem['roominfo_name'],
                        'payment_before' => $subOrderItem['payment'],
                        'status_before' => $subOrderItem['status'],
                        'checkoutdate' => '',
                        'realnight' => '',
                    );
                    // 订单已入住的情况修改实住晚数
                    if ($subOrderItem['status'] == ORDER_CHECKINED) {
                        if ($checkinType === 1) {
                            if ($today > $subOrderItem['checkoutdate']) {
                                $orderRoomToDeleteItem['checkoutdate'] = $subOrderItem['checkoutdate'];
                                $orderRoomToDeleteItem['realnight'] = 0;
                                $orderRoomToDeleteItem['hour'] = $subOrderItem['hour'];
                            } else {
                                $orderRoomToDeleteItem['checkoutdate'] = $today;
                                $orderRoomToDeleteItem['realnight'] = 0;
                                $orderRoomToDeleteItem['hour'] = 0;
                            }
                        } else {
                            $orderRoomToDeleteItem['checkoutdate'] = substr($today, 0, 11) . '00:00:00';
                            $orderRoomToDeleteItem['realnight'] = getNight(strtotime($subOrderItem['startdate']), strtotime($orderRoomToDeleteItem['checkoutdate']));
                        }
                    } else {
                        $orderRoomToDeleteItem['checkoutdate'] = $subOrderItem['checkoutdate'];
                        $orderRoomToDeleteItem['realnight'] = 0;
                        $orderRoomToDeleteItem['hour'] = 0;
                        $orderRoomToDeleteItem['month'] = 0;
                    }
                    array_push($orderRoomToDelete, $orderRoomToDeleteItem);

                    foreach ($subOrderItem['user'] as $orderUserItem) {
                        // 已经删除的同住人不管
                        if ($orderUserItem['isdelete'] == IS_DELETE) {
                            continue;
                        }

                        array_push($orderUserToDelete['orderuser_id'], $orderUserItem['orderuser_id']);
                        array_push($orderUserToDelete['userroom_id'], $orderUserItem['userroom_id']);
                        array_push($orderUserToDelete['data'], array(
                            'name_before' => $orderUserItem['name'],
                            'areacode_before' => $orderUserItem['areacode'],
                            'mobile_before' => $orderUserItem['mobile'],
                            'identity_before' => $orderUserItem['identity'],
                            'idsex_before' => $orderUserItem['idsex'],
                            'idnation_before' => $orderUserItem['idnation'],
                            'idaddress_before' => $orderUserItem['idaddress'],
                        ));
                    }
                    unset($orderUserItem);

                    continue;
                }

                // 修改订单情况
                // 已取消,已过期订单不允许修改
                if (in_array($subOrderItem['status'], array(ORDER_CANCELED, ORDER_OUTDATED))) {
                    continue;
                }
                $discount += $frontSubOrderItem['nights'];
                $month += $frontSubOrderItem['month'];
                $orderRoomToEditItem = array(
                    'orderroom_id' => $subOrderItem['id'],
                    'status' => $subOrderItem['status'],
                    'status_before' => $subOrderItem['status'],
                    'roomtype_name_before' => $subOrderItem['roomtype_name'],
                    'roominfo_name_before' => $subOrderItem['roominfo_name'],
                    'roominfo_from_before' => $subOrderItem['roominfo_from'],
                    'roomtype_name' => $roomInfo[$frontSubOrderItem['roomId']]['roomtype_name'],
                    'roominfo_name' => $roomInfo[$frontSubOrderItem['roomId']]['name'],
                    'roominfo_from' => $roomInfo[$frontSubOrderItem['roomId']]['roomfrom'],
                    'payment' => $subOrderItem['payment'],
                    'payment_before' => $subOrderItem['payment'],
                    'startdate' => $subOrderItem['startdate'],
                    'startdate_before' => $subOrderItem['startdate'],
                    'enddate' => $subOrderItem['enddate'],
                    'enddate_before' => $subOrderItem['enddate'],
                );
                $subOrderDateChange = false;
                $subOrderRoomChange = false;
                $checkinTime = $canPreGetCard && in_array($frontSubOrderItem['arrayIndex'], $canPreGetCardIndex) ? $currentCheckinTime : $hotelCheckinTime;
                if ($subOrderItem['startdate'] != $frontSubOrderItem['startdate'] || $subOrderItem['checkoutdate'] != $frontSubOrderItem['enddate'] || ($subOrderItem['hour'] != $frontSubOrderItem['hour'] && isset($frontSubOrderItem['hour'])) || $subOrderItem['payment'] != $frontSubOrderItem['payment']) {
                    $subOrderDateChange = true;
                    $orderRoomToEditItem['startdate'] = $frontSubOrderItem['startdate'];
                    $orderRoomToEditItem['enddate'] = $frontSubOrderItem['enddate'];
                    $orderRoomToEditItem['roominfo_id'] = $frontSubOrderItem['roomId'];
                    $orderRoomToEditItem['night'] = $frontSubOrderItem['nights'];
                    $orderRoomToEditItem['checkoutdate'] = $frontSubOrderItem['enddate'];
                    $orderRoomToEditItem['realnight'] = $frontSubOrderItem['nights'];
                    $orderRoomToEditItem['hour'] = $frontSubOrderItem['hour'];
                    $orderRoomToEditItem['month'] = $frontSubOrderItem['month'];
                    $orderRoomToEditItem['payment'] = $frontSubOrderItem['payment'];
                }
                /*if ($subOrderItem['payment'] != $frontSubOrderItem['payment']) {
                    $orderRoomToEditItem['payment'] = $frontSubOrderItem['payment'];
                }*/
                if ($subOrderItem['roominfo_id'] != $frontSubOrderItem['roomId']) {
                    $subOrderRoomChange = true;
                    $orderRoomToEditItem['roominfo_id'] = $frontSubOrderItem['roomId'];
                    $orderRoomToEditItem['night'] = $frontSubOrderItem['nights'];
                    $orderRoomToEditItem['hour'] = $frontSubOrderItem['hour'];
                    $orderRoomToEditItem['realnight'] = $frontSubOrderItem['nights'];
                    $orderRoomToEditItem['checkoutdate'] = $frontSubOrderItem['enddate'];
                }
                //已入住的状态保持
                if ($subOrderJustPayed && $subOrderItem['status']!=2 && $subOrderItem['status']!=3) {
                    $orderRoomToEditItem['status'] = ORDER_PAYED;
                    $orderRoomToEditItem['status_before'] = ORDER_BOOKED;
                }

                // 检查时间段内是否是维修时间
                if (isset($roomServiceList[$orderRoomToEditItem['roominfo_id']])) {
                    $roomServiceStartDate = date('Y-m-d', $roomServiceList[$orderRoomToEditItem['roominfo_id']]['startdate']);
                    $roomServiceEndDate = date('Y-m-d', $roomServiceList[$orderRoomToEditItem['roominfo_id']]['enddate']);
                    $roomServiceDateArray = getDatesBetweenTime($roomServiceStartDate, $roomServiceEndDate, true);
                    // 是否夜审订单 ismidnightorder=1
                    if ($subOrderItem['ismidnightorder'] == 1) {
                        $orderDateArray = getDatesBetweenTime($orderRoomToEditItem['startdate'], $orderRoomToEditItem['enddate'], true);
                    } else {
                        $orderDateArray = getDatesBetweenTime($orderRoomToEditItem['startdate'], $orderRoomToEditItem['enddate']);
                    }
                    if (!empty(array_intersect($roomServiceDateArray, $orderDateArray))) {
                        throw new \Exception('403,514', 514);
                    }
                }

                if ($subOrderDateChange || $subOrderRoomChange || $subOrderJustPayed) {
                    array_push($orderRoomToEdit, $orderRoomToEditItem);
                    // 订单房间||时间存在修改,准备修改统计的数据
                    if ($subOrderDateChange || $subOrderRoomChange) {
                        array_push($orderChangeTaskEditData, array(
                            'status' => isset($orderRoomToEditItem['status']) ? $orderRoomToEditItem['status'] : $subOrderItem['status'],
                            'startdate' => isset($orderRoomToEditItem['startdate']) ? $orderRoomToEditItem['startdate'] : $subOrderItem['startdate'],
                            'checkoutdate' => isset($orderRoomToEditItem['enddate']) ? $orderRoomToEditItem['enddate'] : $subOrderItem['enddate'],
                            'payment' => isset($orderRoomToEditItem['payment']) ? $orderRoomToEditItem['payment'] : $subOrderItem['payment'],
                            'night' => isset($orderRoomToEditItem['night']) ? $orderRoomToEditItem['night'] : $subOrderItem['night'],
                            'hour' => isset($orderRoomToEditItem['hour']) ? $orderRoomToEditItem['hour'] : $subOrderItem['hour'],
                            'hotelentity_id' => $hotelId,
                            'roominfo_id' => isset($orderRoomToEditItem['roominfo_id']) ? $orderRoomToEditItem['roominfo_id'] : $subOrderItem['roominfo_id'],
                            'id' => $subOrderItem['id'],
                        ));
                    }
                }
                // 查看订单同住人修改&删除情况
                foreach ($subOrderItem['user'] as $orderUserItem) {
                    $frontOrderUserItem = isset($frontSubOrderItem['users'][$orderUserItem['orderuser_id']]) ? $frontSubOrderItem['users'][$orderUserItem['orderuser_id']][0] : null;

                    // 同住人删除,已删除的同住人不能删除
                    if (is_null($frontOrderUserItem) && $orderUserItem['isdelete'] != IS_DELETE) {
                        array_push($orderUserToDelete['orderuser_id'], $orderUserItem['orderuser_id']);
                        array_push($orderUserToDelete['userroom_id'], $orderUserItem['userroom_id']);
                        array_push($orderUserToDelete['data'], array(
                            'name_before' => $orderUserItem['name'],
                            'areacode_before' => $orderUserItem['areacode'],
                            'mobile_before' => $orderUserItem['mobile'],
                            'identity_before' => $orderUserItem['identity'],
                            'idsex_before' => $orderUserItem['idsex'],
                            'idnation_before' => $orderUserItem['idnation'],
                            'idaddress_before' => $orderUserItem['idaddress'],
                        ));

                        // 保存需要删除的同住人房卡
                        if ($subOrderItem['status'] == ORDER_CHECKINED) {
                            array_push($editOrderCardTaskOldData, array(
                                'areacode' => $orderUserItem['areacode'],
                                'mobile' => $orderUserItem['mobile'],
                                'roomName' => $subOrderItem['roominfo_name'],
                                'orderRoomId' => $subOrderItem['id'],
                            ));
                        }
                        continue;
                    }

                    // 同住人修改
                    $orderUserToEditItem = array();
                    if ($orderUserItem['name'] != $frontOrderUserItem['name'] || $orderUserItem['mobile'] != $frontOrderUserItem['mobile'] || $orderUserItem['identity'] != $frontOrderUserItem['identity'] || $subOrderDateChange || $subOrderRoomChange || $orderUserItem['areacode'] != $frontOrderUserItem['areacode'] || $orderUserItem['idsex'] != $frontOrderUserItem['idsex'] || $orderUserItem['idnation'] != $frontOrderUserItem['idnation'] || $orderUserItem['idaddress'] != $frontOrderUserItem['idaddress']) {
                        $userMobileChange = false;
                        $orderUserToEditItem = array(
                            'userlogin_id' => $orderUserItem['userlogin_id'],
                            'orderuser_id' => $orderUserItem['orderuser_id'],
                            'name' => $orderUserItem['name'],
                            'name_before' => $orderUserItem['name'],
                            'areacode' => $orderUserItem['areacode'],
                            'mobile' => $orderUserItem['mobile'],
                            'areacode_before' => $orderUserItem['areacode'],
                            'mobile_before' => $orderUserItem['mobile'],
                            'identity' => $orderUserItem['identity'],
                            'identity_before' => $orderUserItem['identity'],
                            'idsex' => $orderUserItem['idsex'],
                            'idsex_before' => $orderUserItem['idsex'],
                            'idnation' => $orderUserItem['idnation'],
                            'idnation_before' => $orderUserItem['idnation'],
                            'idaddress' => $orderUserItem['idaddress'],
                            'idaddress_before' => $orderUserItem['idaddress'],
                        );
                        if ($orderUserItem['name'] != $frontOrderUserItem['name']) {
                            $orderUserToEditItem['name'] = $frontOrderUserItem['name'];
                        }
                        if ($orderUserItem['mobile'] != $frontOrderUserItem['mobile']) {
                            $userMobileChange = true;
                            $newOrderUserAreaCode = isset($frontOrderUserItem['areacode']) ? $frontOrderUserItem['areacode'] : '86';
                            $newOrderUserMobile = isset($frontOrderUserItem['mobile']) ? $frontOrderUserItem['mobile'] : '';
                            $orderUserToEditItem['areacode'] = $newOrderUserAreaCode;
                            $orderUserToEditItem['mobile'] = $newOrderUserMobile;
                            if (!empty($newOrderUserMobile)) {
                                $userloginId = $userLoginLogic->checkRegister($newOrderUserMobile, false, $newOrderUserAreaCode);
                                if (empty($userloginId)) {
                                    $orderUserToEditItem['userlogin_id'] = 0;
                                } else {
                                    $orderUserToEditItem['userlogin_id'] = $userloginId;
                                }
                            } else {
                                $orderUserToEditItem['userlogin_id'] = 0;
                            }
                        }
                        // 保存需要删除或增加的同住人房卡
                        if ($subOrderItem['status'] == ORDER_CHECKINED) {
                            if (!empty($orderUserToEditItem['mobile_before'])) {
                                array_push($editOrderCardTaskOldData, array(
                                    'mobile' => $orderUserToEditItem['mobile_before'],
                                    'areacode' => $orderUserToEditItem['areacode_before'],
                                    'roomName' => $subOrderItem['roominfo_name'],
                                    'orderRoomId' => $subOrderItem['id'],
                                ));
                            }
                            if ($orderUserItem['isdelete'] == NOT_DELETE) {
                                array_push($editOrderCardTaskNewData, array(
                                    'areacode' => $orderUserToEditItem['areacode'],
                                    'mobile' => $orderUserToEditItem['mobile'],
                                    'roomName' => $subOrderRoomChange ? $orderRoomToEditItem['roominfo_name'] : $subOrderItem['roominfo_name'],
                                    'orderRoomId' => $subOrderItem['id'],
                                    // 原来的开始结束时间
                                    'startdate' => $checkinType === 1 ? $frontSubOrderItem['startdate'] : substr($frontSubOrderItem['startdate'], 0, 11) . $checkinTime,
                                    'enddate' => $checkinType === 1 ? $frontSubOrderItem['enddate'] : substr($frontSubOrderItem['enddate'], 0, 11) . $hotelCheckoutTime,
                                    // 修改手机号不发送短信
                                    'sendMessage' => false,
                                ));
                            }
                        }
                        if ($orderUserItem['identity'] != $frontOrderUserItem['identity']) {
                            $orderUserToEditItem['identity'] = isset($frontOrderUserItem['identity']) ? $frontOrderUserItem['identity'] : '';
                        }
                        if ($orderUserItem['idsex'] != $frontOrderUserItem['idsex']) {
                            $orderUserToEditItem['idsex'] = isset($frontOrderUserItem['idsex']) ? $frontOrderUserItem['idsex'] : '';
                        }
                        if ($orderUserItem['idnation'] != $frontOrderUserItem['idnation']) {
                            $orderUserToEditItem['idnation'] = isset($frontOrderUserItem['idnation']) ? $frontOrderUserItem['idnation'] : '';
                        }
                        if ($orderUserItem['idaddress'] != $frontOrderUserItem['idaddress']) {
                            $orderUserToEditItem['idaddress'] = isset($frontOrderUserItem['idaddress']) ? $frontOrderUserItem['idaddress'] : '';
                        }
                        // 房间信息变化,或userlogin_id变化
                        if ($userMobileChange || $subOrderDateChange || $subOrderRoomChange) {
                            $orderUserToEditItem['userroom_id'] = $orderUserItem['userroom_id'];
                            $orderUserToEditItem['orderroom_id'] = $subOrderItem['id'];
                            $orderUserToEditItem['roominfo_id'] = $subOrderRoomChange ? $frontSubOrderItem['roomId'] : $subOrderItem['roominfo_id'];
                            $orderUserToEditItem['startdate'] = $subOrderDateChange ? $checkinType === 1 ? $frontSubOrderItem['startdate'] : substr($frontSubOrderItem['startdate'], 0, 11) . $checkinTime : $orderUserItem['startdate'];
                            $orderUserToEditItem['enddate'] = $subOrderDateChange ? $checkinType === 1 ? $frontSubOrderItem['enddate'] : substr($frontSubOrderItem['enddate'], 0, 11) . $hotelCheckoutTime : $orderUserItem['enddate'];
                        }

                        array_push($orderUserToEdit, $orderUserToEditItem);
                    }
                }
                unset($orderUserItem);

                // 订单同住人增加
                if (isset($frontSubOrderItem['users'][0])) {
                    foreach ($frontSubOrderItem['users'][0] as $newOrderUserItem) {
                        $orderUserToAddItem = array(
                            'userlogin_id' => 0,
                            'roominfo_id' => $frontSubOrderItem['roomId'],
                            'startdate' => $checkinType === 1 ? $frontSubOrderItem['startdate'] : substr($frontSubOrderItem['startdate'], 0, 11) . $checkinTime,
                            'enddate' => $checkinType === 1 ? $frontSubOrderItem['enddate'] : substr($frontSubOrderItem['enddate'], 0, 11) . $hotelCheckoutTime,
                            'name' => $newOrderUserItem['name'],
                            'areacode' => isset($newOrderUserItem['areacode']) ? $newOrderUserItem['areacode'] : '86',
                            'mobile' => isset($newOrderUserItem['mobile']) ? $newOrderUserItem['mobile'] : '',
                            'identity' => isset($newOrderUserItem['identity']) ? $newOrderUserItem['identity'] : '',
                            'idsex' => isset($newOrderUserItem['idsex']) ? $newOrderUserItem['idsex'] : '',
                            'idnation' => isset($newOrderUserItem['idnation']) ? $newOrderUserItem['idnation'] : '',
                            'idaddress' => isset($newOrderUserItem['idaddress']) ? $newOrderUserItem['idaddress'] : '',
                            'orderroom_id' => $subOrderItem['id'],
                            'isdelete' => $subOrderItem['status'] == ORDER_CHECKOUTED ? IS_DELETE : NOT_DELETE,
                        );
                        if (isset($newOrderUserItem['mobile']) && !empty($newOrderUserItem['mobile'])) {
                            $userloginId = $userLoginLogic->checkRegister($newOrderUserItem['mobile'], false, $newOrderUserItem['areacode']);
                            if (!empty($userloginId)) {
                                $orderUserToAddItem['userlogin_id'] = $userloginId;
                            }
                        }
                        array_push($orderUserToAddWhileEdit, $orderUserToAddItem);

                        // 订单增加同住人短信后台服务数据
                        if ($subOrderItem['status'] == ORDER_CHECKINED) {
                            array_push($editOrderCardTaskNewData, array(
                                'areacode' => isset($newOrderUserItem['areacode']) ? $newOrderUserItem['areacode'] : '86',
                                'mobile' => $newOrderUserItem['mobile'],
                                'roomName' => $subOrderRoomChange ? $orderRoomToEditItem['roominfo_name'] : $subOrderItem['roominfo_name'],
                                'orderRoomId' => $subOrderItem['id'],
                                'startdate' => $orderUserToAddItem['startdate'],
                                'enddate' => $orderUserToAddItem['enddate'],
                                // 增加同住人不发送短信
                                'sendMessage' => false,
                            ));
                        }
                    }
                    unset($newOrderUserItem);
                }
            }
            unset($subOrderItem);
            unset($frontSubOrderItem);
            // 增加订单情况
            if (isset($frontSubOrders[0])) {
                $currentHour = date('H:i');
                foreach ($frontSubOrders[0] as $index => $frontSubOrderItem) {
                    $ismidnightorder = 0;
                    if (date('Y-m-d') == date('Y-m-d', strtotime($frontSubOrderItem['startdate'])) && '00:00' < $currentHour && $currentHour < $hotelOrderDiffTime) {
                        $hotelOrderDiffTimeType = 1;
                        $ismidnightorder = 1;
                        // 在凌晨00:00 至 预定(直接入住)分割时间 之间预定需要从新算结束时间 （预定(直接入住)分割时间 到 最迟退房时间 算一天 列：2017-11-02 + $hotelOrderDiffTime - 2017-11-02 + $hotelCheckinTime 算一天）
                        if ($frontSubOrderItem['nights'] == 1) {
                            $orderEndDate = $frontSubOrderItem['enddate'] = $frontSubOrderItem['orderDate'] . " 00:00:00";
                        } else {
                            $orderEndDate = $frontSubOrderItem['enddate'] = getOrderEndTime($frontSubOrderItem['orderDate'], $frontSubOrderItem['nights'] - 1, $frontSubOrderItem['hour']);
                        }
                    } else {
                        $hotelOrderDiffTimeType = 0;
                        $orderEndDate = getOrderEndTime($frontSubOrderItem['orderDate'], $frontSubOrderItem['nights'], $frontSubOrderItem['hour']);
                    }
                    $newOrderStatus = $this->getOrderStatus(getOrderStartTime($frontSubOrderItem['orderDate']), $orderEndDate, 1, $newStatus, $hotelCheckoutTime, $checkinType, $hotelOrderDiffTimeType);
                    $checkinTime = $canPreGetCard && $newOrderStatus == ORDER_CHECKINED && in_array($frontSubOrderItem['arrayIndex'], $canPreGetCardIndex) ? $currentCheckinTime : $hotelCheckinTime;
                    $discount += $frontSubOrderItem['nights'];
                    $month += $frontSubOrderItem['month'];

                    // 检查时间段内是否是维修时间
                    if (isset($roomServiceList[$frontSubOrderItem['roomId']])) {
                        $roomServiceStartDate = date('Y-m-d', $roomServiceList[$frontSubOrderItem['roomId']]['startdate']);
                        $roomServiceEndDate = date('Y-m-d', $roomServiceList[$frontSubOrderItem['roomId']]['enddate']);
                        $roomServiceDateArray = getDatesBetweenTime($roomServiceStartDate, $roomServiceEndDate, true);
                        // 是否夜审订单 ismidnightorder=1
                        if ($ismidnightorder == 1) {
                            $orderDateArray = getDatesBetweenTime($frontSubOrderItem['startdate'], $frontSubOrderItem['enddate'], true);
                        } else {
                            $orderDateArray = getDatesBetweenTime($frontSubOrderItem['startdate'], $frontSubOrderItem['enddate']);
                        }
                        if (!empty(array_intersect($roomServiceDateArray, $orderDateArray))) {
                            throw new \Exception('403,514', 514);
                        }
                    }

                    array_push($orderRoomToAdd, array(
                        'roominfo_id' => $frontSubOrderItem['roomId'],
                        'creator' => $operator,
                        'hour' => isset($frontSubOrderItem['hour']) ? $frontSubOrderItem['hour'] : 0,
                        'month' => isset($frontSubOrderItem['month']) ? $frontSubOrderItem['month'] : 0,
                        'night' => $frontSubOrderItem['nights'],
                        'realnight' => $frontSubOrderItem['nights'],
                        'startdate' => $frontSubOrderItem['startdate'],
                        'enddate' => $frontSubOrderItem['enddate'],
                        'checkindate' => $today,
                        'checkoutdate' => $frontSubOrderItem['enddate'],
                        'roomtype_name' => $roomInfo[$frontSubOrderItem['roomId']]['roomtype_name'],
                        'roominfo_name' => $roomInfo[$frontSubOrderItem['roomId']]['name'],
                        'roominfo_from' => $roomInfo[$frontSubOrderItem['roomId']]['roomfrom'],
                        'payment' => $frontSubOrderItem['payment'],
                        'status' => $newOrderStatus,
                        'ismidnightorder' => $ismidnightorder,
                    ));
                    // 增加订单入住人
                    $orderUserToAdd['data'][$index] = array();
                    foreach ($frontSubOrderItem['users'][0] as $orderUserItem) {
                        $orderUserToAddItem = array(
                            'userlogin_id' => 0,
                            'roominfo_id' => $frontSubOrderItem['roomId'],
                            'startdate' => $checkinType === 1 ? $frontSubOrderItem['startdate'] : substr($frontSubOrderItem['startdate'], 0, 11) . $checkinTime,
                            'enddate' => $checkinType === 1 ? $frontSubOrderItem['enddate'] : substr($frontSubOrderItem['enddate'], 0, 11) . $hotelCheckoutTime,
                            'name' => $orderUserItem['name'],
                            'areacode' => isset($orderUserItem['areacode']) ? $orderUserItem['areacode'] : '86',
                            'mobile' => $orderUserItem['mobile'],
                            'identity' => $orderUserItem['identity'],
                            'idsex' => $orderUserItem['idsex'],
                            'idnation' => $orderUserItem['idnation'],
                            'idaddress' => $orderUserItem['idaddress'],
                            'isdelete' => $newOrderStatus == ORDER_CHECKOUTED ? IS_DELETE : NOT_DELETE,
                        );
                        if (!empty($orderUserItem['mobile'])) {
                            $userloginId = $userLoginLogic->checkRegister($orderUserItem['mobile'], false, $orderUserItem['areacode']);
                            if (!empty($userloginId)) {
                                $orderUserToAddItem['userlogin_id'] = $userloginId;
                            }
                        }
                        array_push($orderUserToAdd['data'][$index], $orderUserToAddItem);

                        // 每个订单同住人保存房卡后台任务调用数据
                        if (!isset($addOrderCardTaskData[$index])) {
                            $addOrderCardTaskData[$index] = array();
                        }
                        if (!$newOrderStatus == ORDER_CHECKINED && !empty($orderUserToAddItem['mobile'])) {
                            array_push($addOrderCardTaskData[$index], array(
                                'startdate' => $orderUserToAddItem['startdate'],
                                'enddate' => $orderUserToAddItem['enddate'],
                                'areacode' => isset($orderUserToAddItem['areacode']) ? $orderUserToAddItem['areacode'] : '86',
                                'mobile' => $orderUserToAddItem['mobile'],
                                'roomName' => $roomInfo[$frontSubOrderItem['roomId']]['name'],
                            ));
                        }
                    }
                    unset($orderUserItem);
                }
                unset($frontSubOrderItem);
            }

            // 订单金额修改情况
            $otherReceivePrice = 0;
            if (!empty($receives)) {
                $orderPayNeedEdit = 1;
                foreach ($receives as $receiveItem) {
                    $value = abs($receiveItem['value']);
                    if (in_array($receiveItem['category'], array(PAY_CHANGE_RECEIPT, PAY_CHANGE_REFUND))) {
                        array_push($orderReceiveChangeData, array(
                            'id' => $receiveItem['type'],
                            'pay' => $receiveItem['category'] == PAY_CHANGE_RECEIPT ? $value : -$value,
                            'transBeforeValue' => $receiveItem['transBeforeValue'],
                            'currencyId' => $receiveItem['transCurrencyId'],
                        ));
                    } else if (in_array($receiveItem['category'], array(PAY_CHANGE_DEPOSIT, PAY_CHANGE_DEPOSIT_BACK))) {
                        array_push($orderDepositChangeData, array(
                            'id' => $receiveItem['type'],
                            'pay' => $receiveItem['category'] == PAY_CHANGE_DEPOSIT ? $value : -$value,
                            'transBeforeValue' => $receiveItem['transBeforeValue'],
                            'currencyId' => $receiveItem['transCurrencyId'],
                        ));
                    }  else {
                        // 其他消费 (包含其他消费代收)
                        array_push($orderReceiveChangeData, array(
                            'pay' => $value,
                            'id' => $receiveItem['type'],
                            'category' => $receiveItem['category'],
                            'transBeforeValue' => $receiveItem['transBeforeValue'],
                            'currencyId' => $receiveItem['transCurrencyId'],
                        ));
                        if ($receiveItem['type'] != 0) {
                            // 订单金额加上 新的其他消费已收金额
                            $otherReceivePrice += $value;
                        }
                    }
                }
                unset($receiveItem);
            }

            // 支付记录修改情况
            if (!empty($orderPayRecord)) {
                $orderPayRecordModel = D('OrderPayRecord');
                foreach ($orderPayRecord as $key => $orderPayRecordItem) {
                    // 与默认货币id不相等 则需要价格汇率转换
                    $orderPayRecordItem['trans_before_pay'] = $orderPayRecordItem['pay'];
                    if ($orderPayRecordItem['transCurrencyId'] != 0 && $orderPayRecordItem['currencyId'] != $orderPayRecordItem['transCurrencyId']) {
                        $currencyLogic = A('Common/Currency', 'Logic');
                        $orderPayRecordItem['pay'] = $currencyLogic->exchangeRates($orderPayRecordItem['transCurrencyId'], $orderPayRecordItem['currencyId'], $orderPayRecordItem['pay']);
                    }

                    $orderPayRecordDetail = $orderPayRecordModel->getOrderPayRecordById($orderPayRecordItem['id']);
                    if ($orderPayRecordDetail['hotelpay_id'] != $orderPayRecordItem['hotelPayId'] || $orderPayRecordDetail['type'] != $orderPayRecordItem['type'] || $orderPayRecordDetail['pay'] != $orderPayRecordItem['pay'] || $orderPayRecordDetail['currency_id'] != $orderPayRecordItem['transCurrencyId']) {
                        $orderPayRecordNeedEdit = 1;
                        $orderPayNeedEdit = 1;

                        array_push($orderPayRecordEdit, $orderPayRecordItem);

                        // 支付记录修改变化数据
                        $orderPayRecordChangeDataItem = array(
                            'hotelpay_id' => $orderPayRecordItem['hotelPayId'],
                            'type' => $orderPayRecordItem['type'],
                            'pay' => $orderPayRecordItem['pay'],
                            'currency_id' => $orderPayRecordItem['transCurrencyId'],
                            'trans_pay' => $orderPayRecordItem['trans_before_pay'],
                            'hotelpay_id_before' => $orderPayRecordDetail['hotelpay_id'],
                            'type_before' => $orderPayRecordDetail['type'],
                            'pay_before' => $orderPayRecordDetail['pay'],
                            'currency_id_before' => $orderPayRecordDetail['currency_id'],
                            'trans_pay_before' => $orderPayRecordDetail['trans_before_pay'],
                        );
                        array_push($orderPayRecordChangeData, $orderPayRecordChangeDataItem);
                    }
                }
                unset($orderPayRecordItem);

                if (!empty($orderPayRecordEdit)) {
                    // 微预定下的订单不可修改
                    $orderRecordModel = D('OrderRecord');
                    $orderRecordDetail = $orderRecordModel->getOrderRecordByorderId($orderId);
                    if ($orderRecordDetail['recordfrom'] == ORDER_CHANGE_BOOK_WEB) {
                        throw new \Exception('403,512', 512);
                    }
                }
            }

            if (!empty($orderRoomToAdd) || !empty($orderRoomToEdit) || !empty($orderRoomToDelete)) {
                $orderRoomNeedEdit = 1;
            }
            if (!empty($orderUserToAdd['data']) || !empty($orderUserToEdit) || !empty($orderUserToDelete['data']) || !empty($orderUserToAddWhileEdit)) {
                $orderUserNeedEdit = 1;
            }
        } else {
            // 父订单信息不能修改,还原父订单信息
            $hotelChannelId = $orderInfo['hotelchannel_id'];
            $bookerMobile = $orderInfo['mobile'];
            $bookerAreaCode = $orderInfo['areacode'];
            $bookerUser = $orderInfo['name'];
            $bookerIdentity = $orderInfo['identity'];
        }
        // 父订单信息是否需要修改由 (备注是否需要修改 + 来源,预定人是否需要修改) 决定
        $orderInfoNeedEdit = $orderInfoExceptRemarkNeedEdit == 1 || $remarkNeedUpdate || $orderPayNeedEdit ==1 ? 1 : 0;

        // 开始执行修改订单
        if ($orderInfoNeedEdit != 1 && $orderRoomNeedEdit != 1 && $orderUserNeedEdit != 1 && $orderPayNeedEdit != 1 && $orderPayRecordNeedEdit != 1) { 
            // 不需要修改的情况: 
            return true;
        }

        // 开始事务处理
        $orderRecordModel = D('OrderRecord');
        if ($multiTransMode === false) {
            $orderRecordModel->startTrans();
        }
        $commit = true;

        // 生成订单操作记录
        $orderRecordId = null;
        $result = $orderRecordModel->addInfo($orderId, $recordFrom, $paymentChange, $orderInfoNeedEdit, $orderUserNeedEdit, $orderRoomNeedEdit, $operator, $orderPayRecordNeedEdit);
        if ($result == false) {
            $commit = false;
        } else {
            $orderRecordId = $result;
        }

        // 如有会员卡消费 则修改会员卡
        if ($commit && $receives && !empty($vipCard)) {
            $vipCardChannel = isset($vipCard['channel']) ? $vipCard['channel'] : 0;
            $bookingUserId = isset($vipCard['userId']) ? $vipCard['userId'] : 0;
            $result = $this->modifyVipUserCard($hotelId, $vipCard['cardMobile'], $vipCard['cardAreaCode'], $receives, $vipCardChannel, $bookingUserId);
            if ($result == false) {
                $commit = false;
            }
            $vipUserModel = D('VipUser');
            $vipUserInfo = $vipUserModel->getInfoByMobile($hotelId, $vipCard['cardMobile'], $vipCard['cardAreaCode']);
            $vipUserId = $vipUserInfo['id'];
        }

        // 先修改支付记录
        if ($commit && $orderPayNeedEdit == 1) {
            $vipUserId = isset($vipUserId) ? $vipUserId : '0';
            $result = $this->saveOrderPayChange($hotelId, $orderId, $orderRecordId, null, null, $orderPayRecordEdit, $vipUserId);
            if (!$result) {
                $commit = false;
            }
        }

        // 订单其他消费已收金额
        $otherReceiveInfo = $this->getOrderPayRecordSum($orderId);
        // 原来的其他消费已收金额
        $oldOtherReceivePrice = $otherReceiveInfo['otherReceivePrice'];

        // 父订单信息是否需要修改由  原来的其他消费已收金额 或 新的他消费已收金额 不为零时
        if ($otherReceivePrice != 0 || $oldOtherReceivePrice != 0) {
            $orderInfoNeedEdit = 1;
        }

        // 先修改支付记录 再添加支付记录 订单金额变化
        if ($commit && $orderPayNeedEdit == 1) {
            $vipUserId = isset($vipUserId) ? $vipUserId : '0';
            $result = $this->saveOrderPayChange($hotelId, $orderId, $orderRecordId, $orderReceiveChangeData, $orderDepositChangeData, null, $vipUserId);
            if (!$result) {
                $commit = false;
            }
        }

        // 支付记录有修改 重新算 收款 收押金 退款 退押金
        if ($orderPayNeedEdit = 1) {
            $orderPayRecordModel = D('OrderPayRecord');
            $hotelPayRecords = $orderPayRecordModel->getInfosByOrderinfoId($orderId);
            $totalReceipt = $totalDeposit = $totalRefund = $totalRefundDeposit = 0.00;
            foreach ($hotelPayRecords as $hotelPayRecordItem) {
                switch ($hotelPayRecordItem['type']) {
                    case PAY_CHANGE_RECEIPT:// 收款
                        $totalReceipt += (double)$hotelPayRecordItem['pay'];
                        break;
                    case PAY_CHANGE_DEPOSIT:// 收押金
                        $totalDeposit += (double)$hotelPayRecordItem['pay'];
                        break;
                    case PAY_CHANGE_REFUND:// 退款
                        $totalRefund += (double)$hotelPayRecordItem['pay'];
                        break;
                    case PAY_CHANGE_DEPOSIT_BACK://  
                        $totalRefundDeposit += (double)$hotelPayRecordItem['pay'];
                        break;
                    default;
                        // 加上 其他消费已收
                        if ($hotelPayRecordItem['hotelpay_id'] != 0) {
                            $totalReceipt += (double)$hotelPayRecordItem['pay'];
                        }
                        break;
                }
            }
            unset($hotelPayRecordItem);

            $receiptNew = $totalReceipt;
            $depositNew = $totalDeposit;
            $receiptNew = $receiptNew > 999999.99 ? 999999.99 : $receiptNew;
            $depositNew = $depositNew > 999999.99 ? 999999.99 : $depositNew;
        }

        // 保存支付记录变化记录
        if ($commit && $orderPayRecordNeedEdit == 1) {
            $result = $this->saveOrderPayRecordChange($orderRecordId, $orderPayRecordChangeData);
            if (!$result) {
                $commit = false;
            }
        }

        // 修改父订单信息
        if ($commit && $orderInfoNeedEdit) {
            $orderInfoChangeData = array(
                'hotelchannel_id' => $hotelChannelId,
                'areacode' => $orderInfo['areacode'],
                'mobile' => $orderInfo['mobile'],
                'name' => $orderInfo['name'],
                'identity' => $orderInfo['identity'],
                'remark' => $orderInfo['remark'],
                'hotelchannel_before' => $hotelChannelId,
                'areacode_before' => $orderInfo['areacode'],
                'mobile_before' => $orderInfo['mobile'],
                'name_before' => $orderInfo['name'],
                'identity_before' => $orderInfo['identity'],
                'remark_before' => $orderInfo['remark'],
                'charityPrice' => $charityPrice,
            );
            if ($orderInfoExceptRemarkNeedEdit == 1) {
                if ($orderInfo['hotelchannel_id'] != $hotelChannelId) {
                    $orderInfoChangeData['hotelchannel_before'] = $orderInfo['hotelchannel_id'];
                }
                 if ($orderInfo['areacode'] != $bookerAreaCode) {
                    $orderInfoChangeData['areacode'] = $bookerAreaCode;
                }
                if ($orderInfo['mobile'] != $bookerMobile) {
                    $orderInfoChangeData['mobile'] = $bookerMobile;
                }
                if ($orderInfo['name'] != $bookerUser) {
                    $orderInfoChangeData['name'] = $bookerUser;
                }
                if ($orderInfo['identity'] != $bookerIdentity) {
                    $orderInfoChangeData['identity'] = $bookerIdentity;
                }
            }
            if ($remarkNeedUpdate) {
                $orderInfoChangeData['remark'] = $remark;
            }

            $orderRoomDetail = array_values($orderInfo['rooms']);
            $isMinusPrice = $orderRoomDetail[0]['minusprice'] != '0.00' ? $orderRoomDetail[0]['minusprice'] : false;

            //是否有会员价
            $orderInfoChangeData['orig'] = $payment; //原价
            if($orderInfo['discountrule'] != '0.00'){
                if (!$isMinusPrice) {
                    if($orderInfo['discount']=='1'){
                        $leaveRoomCount = count($orderInfo['rooms']);
                        if (!empty($orderRoomToDelete)) {
                            $leaveRoomCount = $leaveRoomCount - count($orderRoomToDelete);
                        }
                        if (!empty($orderRoomToAdd)) {
                            $leaveRoomCount = $leaveRoomCount + count($orderRoomToAdd);
                        }
                        $leaveRoomCount = $leaveRoomCount - $cancelRoomCount;
                        if ($leaveRoomCount == 0) {
                            $leaveRoomCount = count($orderInfo['rooms']);
                        }

                        if ($month > 0) {
                            $payment = $payment-$orderInfo['discountrule'] * $month;
                        } elseif ($discount > 0) {
                            $payment = $payment-$orderInfo['discountrule'] * $discount;
                        } else {
                            $payment = $payment-$orderInfo['discountrule'] * $leaveRoomCount;
                        }
                    }else{
                        $payment = round($payment*$orderInfo['discountrule']/10,2);
                    }
                }
            }

            if ($isMinusPrice) {
                $payment = $payment - $isMinusPrice;
            }

            // 如该订单有使用优惠券 并且有支付
            if ($commit && $orderPayNeedEdit == 1 && !is_null($couponGetNo)) {
                $hotelCouponModel = D('HotelCoupon');
                $userCouponModel = D('UserCoupon');

                $userCouponId = decodeCouponNumber($couponGetNo, 'UCP');
                $userCouponInfo = $userCouponModel->getUserCouponByGetNo($userCouponId);
                // 获取优惠券信息
                $hotelCouponInfo = $hotelCouponModel->getCouponByIds($userCouponInfo['coupon_id'], true);
                $hotelCouponInfo = $hotelCouponInfo[0];

                // 是否满足满减金额
                if ($payment >= $hotelCouponInfo['price']) {
                    // 1=满减券 2=折扣券
                    if ($hotelCouponInfo['type'] == 1) {
                        $payment = $payment - $hotelCouponInfo['minus_price'];
                    } else if ($hotelCouponInfo['type'] == 2) {
                        $payment = $payment * ($hotelCouponInfo['discount']/10);
                    }

                    // 则修改优惠券已使用
                    $saveResult = $userCouponModel->saveUserCouponOrderId($userCouponId, null, USER_COUPON_USED);
                    if ($saveResult === false) {
                        $commit = false;
                    }
                } else {
                    // 不满足 修改微预定用户优惠券订单id 为 0
                    $saveResult = $userCouponModel->saveUserCouponOrderId($userCouponId, 0, USER_COUPON_OUTDATED);
                    if (!$saveResult) {
                        $commit = false;
                    }
                }
            }

            // 订单应付金额 加上 其他消费已收金额
            $payment += $oldOtherReceivePrice + $otherReceivePrice;
            $orderInfoChangeData['status'] = in_array($orderInfo['status'], [ORDER_CHECKINED, ORDER_CHECKOUTED]) ? $orderInfo['status'] : $newStatus;
            $result = $this->saveOrderInfoChange($hotelId, $orderId, $orderRecordId, $hotelChannelId, $depositNew, $payment, $receiptNew, $bookerUserLoginId, $orderInfoChangeData);
            if (!$result) {
                $commit = false;
            }
        }
        // 子订单修改
        $orderRoomIdIndex = null;
        if ($commit && $orderRoomNeedEdit == 1) {
            $result = $this->changeSubOrder($hotelId, $orderId, $orderRecordId, $orderRoomToAdd, $orderRoomToEdit, $orderRoomToDelete, false);
            if (!$result) {
                $commit = false;
            }
            if (!empty($orderRoomToAdd)) {
                $orderRoomIdIndex = $result;
            }
        }

        // 订单同住人修改
        if ($commit && $orderUserNeedEdit == 1) {
            if (!empty($orderRoomToAdd)) {
                $orderUserToAdd['orderroom_id'] = $orderRoomIdIndex;
            }
            if (empty($orderUserToAdd['data'])) {
                $orderUserToAdd = null;
            }
            if (empty($orderUserToDelete['data'])) {
                $orderUserToDelete = null;
            }
            if (empty($orderUserToAddWhileEdit)) {
                $orderUserToAddWhileEdit = null;
            }

            $result = $this->saveOrderUserChange($hotelId, $orderId, $orderRecordId, $orderUserToAdd, $orderUserToEdit, $orderUserToDelete, $orderUserToAddWhileEdit);
            if (empty($result)) {
                $commit = false;
            }
        }

        // 新增订单,发送到订单变化消息队列
        if ($commit && !empty($orderRoomToAdd)) {
            // 补充封装的逻辑函数需要的字段
            $orderRoomIndexCounter = $orderRoomIdIndex;
            foreach ($orderRoomToAdd as &$orderRoomToAddItem) {
                $orderRoomToAddItem['hotelentity_id'] = $hotelId;
                $orderRoomToAddItem['id'] = $orderRoomIndexCounter;
                $orderRoomIndexCounter++;
            }
            unset($orderRoomToAddItem);
            $result = $this->pushBackendTask($this->backendTaskType['ADD'], NULL, $orderRoomToAdd);
            if (!$result) {
                $commit = false;
            }
        }

        // 修改订单,发送到订单变化消息队列
        if ($commit && !empty($orderChangeTaskEditData)) {
            $result = $this->pushBackendTask($this->backendTaskType['EDIT'], $orderInfo['rooms'], $orderChangeTaskEditData);
            if (!$result) {
                $commit = false;
            }
        }

        // 新增订单,发送到短信消息队列
        if ($commit && !empty($addOrderCardTaskData)) {
            // 用来存放所有同住人房卡
            $addOrderCardTaskData['totalData'] = array();
            // 补充封装的逻辑函数需要的字段
            $orderRoomIndexCounter = $orderRoomIdIndex;
            foreach ($addOrderCardTaskData as $index => $addCardItems) {
                if ($index == 'totalData') {
                    continue;
                }

                if (!empty($addCardItems)) {
                    // 补充子订单ID
                    foreach ($addCardItems as &$addCardItem) {
                        $addCardItem['orderRoomId'] = $orderRoomIndexCounter;
                    }
                    unset($addCardItem);
                    $addOrderCardTaskData['totalData'] = array_merge($addOrderCardTaskData['totalData'], $addCardItems);
                }
                $orderRoomIndexCounter++;
            }
            unset($addCardItems);
            $addOrderCardTaskData = $addOrderCardTaskData['totalData'];

            if (!empty($addOrderCardTaskData)) {
                $this->pushBackendCardTask($this->backendTaskType['ADD'], $hotelId, null, $addOrderCardTaskData);
            }
        }

        // 修改订单,发送到短信消息队列
        if ($commit && (!empty($editOrderCardTaskOldData) || !empty($editOrderCardTaskNewData))) {
            $this->pushBackendCardTask($this->backendTaskType['EDIT'], $hotelId, $editOrderCardTaskOldData, $editOrderCardTaskNewData);
        }

        if ($commit) {
            if ($multiTransMode === false) {
                $orderRecordModel->commit();
            }
            return true;
        } else {
            if ($multiTransMode === false) {
                $orderRecordModel->rollback();
            }
            throw new \Exception('500,509', 509);
        }
    }

    /**
     * 取消订单逻辑
     * 方法会抛异常
     * //TODO   startdate<今天 消息队列
     * @modify trainyao 2016-01-06   创建
     * @modify wenhui 2017-05-03   保存订单信息变化 修改为  不计算新的收款金额与押金
     * @param  integer $hotelId 客栈id
     * @param  integer $orderId 父订单id
     * @param  array $subOrderIds 自订单id数组
     * @param  integer $cancelFrom 修改来源,默认美住web端
     * @param  string $deposit 退款时押金操作,具有正负值(收押金,退押金)
     * @param  integer $depositPay 押金支付方式id
     * @param  string $receipt 退款时收款操作,具有正负值(收款,退款)
     * @param  integer $receiptPay 收退款支付方式id
     * @param  integer $remark 收款时备注
     * @param  integer $operator 操作人id
     * @param bool|mixin $multiTransMode 是否在事务嵌套内,默认否
     * @param integer $receiptBeforeValue 退款时收款转化前金额
     * @param integer $depositBeforeValue 退款时押金转化前金额
     * @param integer $receiptCurrencyId 退款时收款 货币id
     * @param integer $depositCurrencyId 退款时押金 货币id
     * @return mixin 执行结果
     * @throws \Exception
     */
    public function cancelOrder($hotelId, $orderId, $subOrderIds, $cancelFrom = 0, $deposit = null, $depositPay = null, $receipt = null, $receiptPay = null, $remark = null, $operator = null, $multiTransMode = false, $receiptBeforeValue = 0, $depositBeforeValue = 0, $receiptCurrencyId = 0, $depositCurrencyId = 0) {
        // 处理传入数据
        if (!is_array($subOrderIds)) {
            $subOrderIds = explode(',', $subOrderIds);
        }

        // 检查是否有房间权限限制
        try {
            $orderInfo = $this->getOrderInfo($hotelId, $orderId, true, false);
        } catch (\Exception $e) {
            throw $e;
            return false;
        }

        if (empty($orderInfo)) {
            return false;
        }
        $orderRoomInfo = $orderInfo[0]['rooms'];
        if (MODULE_NAME != 'Extend') {
            $adminId = getUserId();
            $adminAuthorityLogic = A('Common/AdminAuthority', 'Logic');
            if (!$adminAuthorityLogic->checkIsAdmin($adminId, $hotelId)) {
                $accountLogic = A('Common/Account', 'Logic');
                $roomAuthority = $accountLogic->getAdminRoomAuthority($adminId, $hotelId);

                // 判断前端传来的房间ID是否都有权限
                if (!empty(array_diff(array_column($orderRoomInfo, 'roominfo_id'), $roomAuthority))) {
                    throw new \Exception('403,202', 202);
                    return false;
                }
            }
        }
        $orderRoomInfo = getArrayValueAsIndex($orderRoomInfo, 'id');
        // 检查子订单id是否都是与父订单关联,顺便生成修改信息数组和收集[已入住]自订单
        $cancelOrderDataArray = array();
        $needChangeRealNightSubOrderData = array();
        $today = date('Y-m-d');
        $todayTimestamp = strtotime($today);
        $now = date('Y-m-d H:i:s');
        //检查客栈是否启用
        $hotelLogic = A('Common/Hotel', 'Logic');
        $hotelLogic->checkHotelActive($hotelId);
        $hotelLogic->checkHotelStatus($hotelId);

        $currentSubOrderIds = array_column($orderRoomInfo, 'id');
        $orderUserToDelete = array(
            'orderuser_id' => array(),
            'userroom_id' => array(),
            'data' => array(),
        );

        // 统计过期子订单ID,获取redis订单,将有效已过期订单转为已预订
        $outDateOrderRoomIds = array();
        foreach ($subOrderIds as $id) {
            if (!in_array($id, $currentSubOrderIds)) {
                throw new \Exception('403,202', 202);
            }
            if ($orderRoomInfo[$id]['status'] == ORDER_OUTDATED) {
                array_push($outDateOrderRoomIds, $id);
            }
        }
        unset($id);
        if (!empty($outDateOrderRoomIds)) {
            $orderRoomModel = D('OrderRoom');
            $redisOrderRecordInfo = $orderRoomModel->getInfoInRedisByHotelRoomOrderRoom($hotelId, null, $outDateOrderRoomIds);
            if ($redisOrderRecordInfo === false) {
                // redis查询失败
                throw new \Exception('500,506', 506);
            }
            foreach ($redisOrderRecordInfo as $redisOrderRecordItem) {
                $orderRoomInfo[$redisOrderRecordItem['orderroom_id']]['status'] = ORDER_BOOKED;
            }
            unset($redisOrderRecordItem);
        }
        $paymentNew = 0;
        foreach ($subOrderIds as $id) {
            $currentStatus = $orderRoomInfo[$id]['status'];
            if (in_array($currentStatus, array(ORDER_CANCELED, ORDER_CHECKOUTED, ORDER_OUTDATED))) {
                continue;
            }

            // 收集子订单用户变化信息
            foreach ($orderRoomInfo[$id]['user'] as $userRoomInfo) {
                // 已删除的同住人不再删除
                if ($userRoomInfo['isdelete'] == IS_DELETE) {
                    continue;
                }
                
                array_push($orderUserToDelete['userroom_id'], $userRoomInfo['userroom_id']);
                array_push($orderUserToDelete['orderuser_id'], $userRoomInfo['orderuser_id']);
                array_push($orderUserToDelete['data'], array(
                    'name_before' => $userRoomInfo['name'],
                    'areacode_before' => $userRoomInfo['areacode'],
                    'mobile_before' => $userRoomInfo['mobile'],
                    'identity_before' => $userRoomInfo['identity'],
                ));
            }
            unset($userRoomInfo);

            // 收集子订单变化信息
            $roomTypeName = $orderRoomInfo[$id]['roomtype_name'];
            $roomInfoName = $orderRoomInfo[$id]['roominfo_name'];

            $cancelOrderDataItem = array(
                'orderroom_id' => $id,
                'roomtype_name_before' => $roomTypeName,
                'roominfo_name_before' => $roomInfoName,
                'status_before' => $currentStatus,
                'hour' => 0,
            );
            // 订单已入住的情况修改实住晚数
            if ($currentStatus == ORDER_CHECKINED) {
                if ($orderRoomInfo[$id]['hour'] > 0) {
                    if ($now > $orderRoomInfo[$id]['checkoutdate']) {
                        $cancelOrderDataItem['checkoutdate'] = $orderRoomInfo[$id]['checkoutdate'];
                        $cancelOrderDataItem['realnight'] = 0;
                        $cancelOrderDataItem['hour'] = $orderRoomInfo[$id]['hour'];
                    } else {
                        $cancelOrderDataItem['checkoutdate'] = $now;
                        $cancelOrderDataItem['realnight'] = 0;
                        $cancelOrderDataItem['hour'] = 0;
                    }
                } else {
                    if ($today <= substr($orderRoomInfo[$id]['checkoutdate'], 0, 10)) {
                        $cancelOrderDataItem['checkoutdate'] = $today . ' 00:00:00';
                        $cancelOrderDataItem['realnight'] = getNight(strtotime($orderRoomInfo[$id]['startdate']), $todayTimestamp);
                    } else {
                        $cancelOrderDataItem['checkoutdate'] = $orderRoomInfo[$id]['checkoutdate'];
                        $cancelOrderDataItem['realnight'] = $orderRoomInfo[$id]['realnight'];
                    }
                }
                
            } else {
                $cancelOrderDataItem['checkoutdate'] = $orderRoomInfo[$id]['checkoutdate'];
                $cancelOrderDataItem['realnight'] = 0;
                $cancelOrderDataItem['hour'] = 0;
                $cancelOrderDataItem['month'] = 0;
            }
            $paymentNew += $orderRoomInfo[$id]['payment'];
            array_push($cancelOrderDataArray, $cancelOrderDataItem);
        }
        unset($id);
        
        // 无需修改的子订单
        if (empty($cancelOrderDataArray)) {
            throw new \Exception('200,200', 200);
        }

        // 执行修改
        $orderRoomModel = D('OrderRoom');
        if ($multiTransMode === false) {
            $orderRoomModel->startTrans();
        }
        $commit = true;
        // 生成单次操作记录id
        $orderRecordModel = D('OrderRecord');
        $orderRecordId = $orderRecordModel->addInfo($orderId, $cancelFrom, null, $orderChange, null, 1, $operator);
        if (empty($orderRecordId)) {
            $commit = false;
        }
        
        // 删除子订单
        if ($commit) {
            $cancelResult = $this->changeSubOrder($hotelId, $orderId, $orderRecordId, null, null, $cancelOrderDataArray, true);
            if (!$cancelResult) {
                $commit = false;
            }
        }

        // 删除已入住子订单的用户-房间信息,订单-用户信息
        if ($commit && !empty($orderUserToDelete['data'])) {
            $cancelResult = $this->saveOrderUserChange($hotelId, $orderId, $orderRecordId, null, null, $orderUserToDelete);
            if (empty($cancelResult)) {
                $commit = false;
            }
        }

        $orderChangeData = array();
        if (!is_null($remark) && $remark != $orderInfo[0]['remark']) {
            $orderChangeData['remark'] = $remark;
            $orderChangeData['remark_before'] = $orderInfo[0]['remark'];
        }
        $orderChangeData['orig'] = $orderInfo[0]['orig'] - $paymentNew;
        if($orderInfo[0]['discountrule'] != '0.00'){
            if($orderInfo[0]['discount']=='1'){
                $paymentNew = $orderInfo[0]['payment'] - $paymentNew * count($subOrderIds) + $orderInfo[0]['discountrule'] * count($subOrderIds);
            }else{
                $paymentNew = number_format($orderChangeData['orig'] * $orderInfo[0]['discountrule'] / 10, 2, '.', '');
            }               
        } else {
            $paymentNew = $orderChangeData['orig'];
        }
        
        // 保存订单信息变化
        if ($commit) {
            $depositNew = $receiptNew = null;
            if (!empty($deposit)) {
                //$depositNew = $orderInfo[0]['deposit'] + $deposit;
                if ($deposit >= 0) {
                    $depositNew = $orderInfo[0]['deposit'] + $deposit;
                } else {
                    $depositNew = $orderInfo[0]['deposit'];
                }
            }
            if (!empty($receipt)) {
                //$receiptNew = $orderInfo[0]['receipt'] + $receipt;
                if ($receipt >=0) {
                    $receiptNew = $orderInfo[0]['receipt'] + $receipt;
                } else {
                    $receiptNew = $orderInfo[0]['receipt'];
                }
            }
            $orderChangeData['status'] = 4;
            $cancelResult = $this->saveOrderInfoChange($hotelId, $orderId, $orderRecordId, null, $depositNew, $paymentNew, $receiptNew, null, $orderChangeData);
            if (empty($cancelResult)) {
                $commit = false;
            }
        }

        // 保存金额变化
        if ($commit) {
            $cancelResult = $this->saveOrderPayChange($hotelId, $orderId, $orderRecordId,
                    array(
                array(
                    'pay' => $receipt,
                    'id' => $receiptPay,
                    'transBeforeValue' => $receiptBeforeValue,
                    'currencyId' => $receiptCurrencyId,
                )
                    ), array(
                array(
                    'pay' => $deposit,
                    'id' => $depositPay,
                    'transBeforeValue' => $depositBeforeValue,
                    'currencyId' => $depositCurrencyId,
                )
                    )
            );
            if (empty($cancelResult)) {
                $commit = false;
            }
        }

        if ($commit) {
            if ($multiTransMode === false) {
                $orderRoomModel->commit();
            }
            //发送取消房卡消息服务
            $messageData = array();
            $orderInfo[0]['rooms'] = getArrayValueAsIndex($orderInfo[0]['rooms'], 'id');
            foreach ($subOrderIds as $subOrderId) {
                $orderRoom = $orderInfo[0]['rooms'][$subOrderId];
                // 删除全部同住人房卡
                foreach ($orderRoom['user'] as $orderUserItem) {
                    $messageData[] = array(
                        'orderRoomId' => $orderRoom['id'],
                        'name' => $orderUserItem['name'],
                        'areacode' => $orderUserItem['areacode'],
                        'mobile' => $orderUserItem['mobile'],
                        'roomName' => $orderRoom['roominfo_name'],
                        'startdate' => $orderRoom['startdate'],
                        'enddate' => $orderRoom['checkoutdate'],
                    );
                }
                unset($orderUserItem);
            }
            unset($subOrderId);

            $this->pushBackendCardTask($this->backendTaskType['CANCEL'], $hotelId, null, $messageData);
            return true;
        } else {
            if ($multiTransMode === false) {
                $orderRoomModel->rollback();
            }
            throw new \Exception('500,506', 506);
            return false;
        }
    }

    /**
     * 办理退房逻辑
     * 方法会抛异常
     * startDate<今天 并且提前退房
     * @modify trainyao 2016-01-06   创建
     * @modify trainyao 2016-07-11   将办理退房同时走第三方支付平台退款逻辑放到公共地方
     * @modify wenhui 2017-05-03   保存订单信息变化 修改为  不计算新的收款金额与押金
     * @param  integer $hotelId 客栈id
     * @param  integer $orderId 父订单id
     * @param  array $subOrderIds 子订单id数组
     * @param  integer $checkoutFrom 修改来源,默认美住web端
     * @param  integer $setDirtySubOrderIds 将哪些房间置为脏房
     * @param  string $receipt 收退款
     * @param  integer $receiptPay 收退款支付方式ID
     * @param  string $deposit 退押金
     * @param  integer $depositPay 退押金支付方式ID
     * @param  string $remark 备注
     * @param  integer $operator 操作人id
     * @param bool|mixin $multiTransMode 是否处在事务嵌套,默认否
     * @param integer $receiptBeforeValue 退款时收款转化前金额
     * @param integer $depositBeforeValue 退款时押金转化前金额
     * @param integer $receiptCurrencyId 退款时收款 货币id
     * @param integer $depositCurrencyId 退款时押金 货币id
     * @return mixin 执行结果
     * @throws \Exception
     */
    public function checkOutOrder($hotelId, $orderId, $subOrderIds, $checkoutFrom = 0, $setDirtySubOrderIds, $receipt = null, $receiptPay = null, $deposit = null, $depositPay = null, $remark = null, $operator = null, $multiTransMode = false, $receiptBeforeValue = 0, $depositBeforeValue = 0, $receiptCurrencyId = 0, $depositCurrencyId = 0) {
        // 处理传入数据
        if (!is_array($subOrderIds)) {
            $subOrderIds = explode(',', $subOrderIds);
        }
        if (!is_array($setDirtySubOrderIds)) {
            $setDirtySubOrderIds = explode(',', $setDirtySubOrderIds);
        }

        // 检查是否有房间权限限制
        try {
            $orderInfo = $this->getOrderInfo($hotelId, $orderId, true, false);
        } catch (\Exception $e) {
            throw $e;
            return false;
        }

        $orderRoomInfo = $orderInfo[0]['rooms'];
        if (MODULE_NAME != 'Extend') {
            $adminId = getUserId();
            $adminAuthorityLogic = A('Common/AdminAuthority', 'Logic');
            if (!$adminAuthorityLogic->checkIsAdmin($adminId, $hotelId)) {
                $accountLogic = A('Common/Account', 'Logic');
                $roomAuthority = $accountLogic->getAdminRoomAuthority($adminId, $hotelId);

                // 判断前端传来的房间ID是否都有权限
                if (!empty(array_diff(array_column($orderRoomInfo, 'roominfo_id'), $roomAuthority))) {
                    throw new \Exception('403,202', 202);
                    return false;
                }
            }

            // 如果办理退房逻辑不在预定端调用, 检查是否有代收记录,是否需要退款操作
            $orderPayInfoModel = D('OrderPayInfo');
            $orderPayInfo = $orderPayInfoModel->getInfoByOrderMethod($subOrderIds);
            if (count($subOrderIds) == 1) {
                $orderPayInfo = array($orderPayInfo);
            }
            // 过滤的掉第三方支付收款方式不是畅联代收的收款记录
            $orderPayInfo = fliterArrayByKey($orderPayInfo, 'type', array(PAY_TYPE_UCLBRT_ALIPAY, PAY_TYPE_UCLBRT_WECHAT));

            $needRefund = false;
            if (!empty($orderPayInfo)) {
                $needRefund = true;

                // 获取客栈支付方式,判断是否需要走第三方平台接口退款流程
                $hotelLogic = A('Common/Hotel', 'Logic');
                $hotelPay = $hotelLogic->getHotelPay($hotelId, false);
                $hotelPay = getArrayValueAsIndex($hotelPay, 'name');
                $wechatPayId = $hotelPay['微信支付']['id'];
                $aliPayId = $hotelPay['支付宝支付']['id'];

                $receiptType = array_column($orderPayInfo, 'paymethod');
                // 使用支付方式作为索引,退款时根据索引获取信息
                $orderPayInfo = getArrayValueAsIndex($orderPayInfo, 'paymethod', 'multi');

                $wechatNeedRefund = false;
                $wechatRefundPrice = 0.00;
                $aliNeedRefund = false;
                $aliRefundPrice = 0.00;
                if (in_array(ORDER_PAY_WECHAT, $receiptType)) {
                    if (!is_null($depositPay) && $depositPay == $wechatPayId) {
                        $wechatRefundPrice = $wechatRefundPrice + (double)abs($deposit);
                    }
                    if (!is_null($receiptPay) && $receiptPay == $wechatPayId) {
                        $wechatRefundPrice = $wechatRefundPrice + (double)abs($receipt);
                    }
                    // 校验退款金额是否大于代收金额
                    if ($wechatRefundPrice > (double)$orderPayInfo[ORDER_PAY_WECHAT][0]['payfee']) {
                        throw new \Exception('403,503', 503);
                        return false;
                    }
                    $wechatNeedRefund = true;
                }
                if (in_array(ORDER_PAY_ALI, $receiptType)) {
                    if (!is_null($depositPay) && $depositPay == $aliPayId) {
                        $aliRefundPrice = $aliRefundPrice + (double)abs($deposit);
                    }
                    if (!is_null($receiptPay) && $receiptPay == $aliPayId) {
                        $aliRefundPrice = $aliRefundPrice + (double)abs($receipt);
                    }
                    // 校验退款金额是否大于代收金额
                    if ($aliRefundPrice > (double)$orderPayInfo[ORDER_PAY_ALI][0]['payfee']) {
                        throw new \Exception('403,503', 503);
                        return false;
                    }
                    $aliNeedRefund = true;
                }
            }
        }
        $orderChange = (!is_null($remark) && $remark != $orderInfo[0]['remark']) ? 1 : NULL;
        $orderRoomInfo = getArrayValueAsIndex($orderRoomInfo, 'id');

        //检查客栈是否启用
        $hotelLogic = A('Common/Hotel', 'Logic');
        $hotelLogic->checkHotelActive($hotelId);
        $hotelLogic->checkHotelStatus($hotelId);

        // 检查子订单id是否都是与父订单关联,顺便生成修改信息数组
        $checkoutOrderDataArray = array();
        $needCheckOutSubOrderIds = array();
        $currentSubOrderIds = array_column($orderRoomInfo, 'id');
        $todayTimestamp = strtotime(date('Y-m-d'));
        $nowTimestamp = strtotime(date('Y-m-d H:i:s'));
        $needChangeRealNightSubOrderData = array();

        foreach ($subOrderIds as $id) {
            if (!in_array($id, $currentSubOrderIds)) {
                throw new \Exception('403,202', 202);
            }
            if ($orderRoomInfo[$id]['status'] == ORDER_CHECKINED || $orderRoomInfo[$id]['status'] == ORDER_SHOULD_CHECKOUT) {
                array_push($needCheckOutSubOrderIds, $id);
                array_push($checkoutOrderDataArray, array(
                    'orderroom_id' => $id,
                    'roomtype_name_before' => $orderRoomInfo[$id]['roomtype_name'],
                    'roominfo_name_before' => $orderRoomInfo[$id]['roominfo_name'],
                    'status_before' => $orderRoomInfo[$id]['status'],
                    'status' => ORDER_CHECKOUTED,
                ));
                if (strtotime($orderRoomInfo[$id]['enddate']) >= $todayTimestamp && $orderRoomInfo[$id]['hour'] == 0) {
                    if ($orderRoomInfo[$id]['ismidnightorder'] == 1) {
                        $todayTimestamp = strtotime(date('Y-m-d',strtotime('+1 day')));
                    }
                    $needChangeRealNightSubOrderData[$id] = array(
                        'realnight' => getNight(strtotime($orderRoomInfo[$id]['startdate']), $todayTimestamp),
                    );
                    // 还原 todayTimestamp
                    $todayTimestamp = strtotime(date('Y-m-d'));
                }
            }
        }
        unset($id);

        // 无需修改的子订单
        if (empty($checkoutOrderDataArray)) {
            throw new \Exception('403,202', 202);
        }

        $orderRoomModel = D('OrderRoom');
        if ($multiTransMode === false) {
            $orderRoomModel->startTrans();
        }
        $commit = true;

        // 生成单次操作记录id
        $orderRecordModel = D('OrderRecord');
        $orderRecordId = $orderRecordModel->addInfo($orderId, $checkoutFrom, null, $orderChange, null, 1, $operator);
        if (empty($orderRecordId)) {
            $commit = false;
        }

        if ($commit) {
            $checkoutResult = $this->changeSubOrder($hotelId, $orderId, $orderRecordId, null, $checkoutOrderDataArray, null);
            if (!$checkoutResult) {
                $commit = false;
            }
        }

        // 更改实际退房时间与实际住多少晚
        if ($commit && !empty($needChangeRealNightSubOrderData)) {
            $today = date('Y-m-d');
            foreach ($needChangeRealNightSubOrderData as $subOrderId => $changeData) {
                $checkoutResult = $orderRoomModel->setCheckoutData($subOrderId, $today, $changeData['realnight']);
                if (!$checkoutResult) {
                    $commit = false;
                    break;
                }
            }
        }

        // 更订单打印退房时间
        if ($commit) {
            $today = date('Y-m-d H:i:s');
            foreach ($currentSubOrderIds as $key => $subOrderId) {
                $checkoutResult = $orderRoomModel->setCheckoutData($subOrderId, null, null, null, $today);
                if (!$checkoutResult) {
                    $commit = false;
                    break;
                }
            }
            unset($subOrderId);
        }

        // 删除已入住子订单的用户-房间信息,订单-用户信息
        if ($commit) {
            $userRoomModel = D('UserRoom');
            $checkoutResult = $userRoomModel->deleteInfoByOrderRoom($needCheckOutSubOrderIds);
            if (!empty($checkoutResult)) {
                $needDeleteOrderUserIds = array();
                foreach ($needCheckOutSubOrderIds as $subOrderId) {
                    $needDeleteOrderUserIds = array_merge($needDeleteOrderUserIds, array_column($orderRoomInfo[$subOrderId]['user'], 'orderuser_id'));
                }
                unset($subOrderId);
                if (!empty($needDeleteOrderUserIds)) {
                    $orderUserModel = D('OrderUser');
                    $checkoutResult = $orderUserModel->deleteInfo($needDeleteOrderUserIds);

                    if (empty($checkoutResult)) {
                        $commit = false;
                    }
                }
            }
        }

        // 把房间置为脏房
        if (!empty($setDirtySubOrderIds) && $commit) {
            $needSetDirtyRoomInfoIds = array();
            foreach ($setDirtySubOrderIds as $id) {
                if (in_array($id, $needCheckOutSubOrderIds)) {
                    array_push($needSetDirtyRoomInfoIds, $orderRoomInfo[$id]['roominfo_id']);
                }
            }
            unset($id);
            if (!empty($needSetDirtyRoomInfoIds)) {
                $roomLogic = A('Common/Room', 'Logic');
                $checkoutResult = $roomLogic->setDirty($hotelId, $needSetDirtyRoomInfoIds, ROOM_DIRTY, true);
                if (empty($checkoutResult)) {
                    $commit = false;
                }
            }
        }

        // 保存订单信息变化
        if ($commit) {
            $orderChangeData = array();
            if ($orderChange) {
                $orderChangeData['remark'] = $remark;
                $orderChangeData['remark_before'] = $orderInfo[0]['remark'];
            }
            if (!empty($deposit)) {
                //$depositNew = $orderInfo[0]['deposit'] + $deposit;
                $depositNew = $orderInfo[0]['deposit'];
            }
            if (!empty($receipt)) {
                //$receiptNew = $orderInfo[0]['receipt'] + $receipt;
                $receiptNew = $orderInfo[0]['receipt'];
            }
            $orderChangeData['status'] = 3;
            $checkoutResult = $this->saveOrderInfoChange($hotelId, $orderId, $orderRecordId, null, $depositNew, null, $receiptNew, null, $orderChangeData);

            if (empty($checkoutResult)) {
                $commit = false;
            }
        }

        // 保存金额变化
        if ($commit) {
            $checkoutResult = $this->saveOrderPayChange($hotelId, $orderId, $orderRecordId,
                    array(
                array(
                    'pay' => $receipt,
                    'id' => $receiptPay,
                    'transBeforeValue' => $receiptBeforeValue,
                    'currencyId' => $receiptCurrencyId,
                )
                    ), array(
                array(
                    'pay' => $deposit,
                    'id' => $depositPay,
                    'transBeforeValue' => $depositBeforeValue,
                    'currencyId' => $depositCurrencyId,
                )
                    )
            );
            if (empty($checkoutResult)) {
                $commit = false;
            }
        }

        // 查看是否需要走退款,走相应流程
        if ($commit && $needRefund) {
            $fileLog = new \Org\Util\FileLog();
            if ($wechatNeedRefund && $wechatRefundPrice != 0.00) {
                // 修改代收记录退款字段
                $checkoutResult = $orderPayInfoModel->saveInfo($orderPayInfo[ORDER_PAY_WECHAT][0]['id'], $wechatRefundPrice);
                if (empty($checkoutResult)) {
                    $commit = false;
                }

                if ($commit) {
                    Vendor('Wechat.WxPayApi');
                    $wechatConfig = C('WECHAT_PAY_CONFIG');
                    $transaction_id = $orderPayInfo[ORDER_PAY_WECHAT][0]['tradenumber'];
                    $totalFee = (double)$orderPayInfo[ORDER_PAY_WECHAT][0]['payfee'] * 100;
                    $wechatRefundPrice = $wechatRefundPrice * 100;

                    $input = new \WxPayRefund();
                    $input->SetTransaction_id($transaction_id);
                    $input->SetTotal_fee($totalFee);
                    $input->SetRefund_fee($wechatRefundPrice);
                    $input->SetOut_refund_no($wechatConfig['mchid'] . date("YmdHis"));
                    $input->SetOp_user_id($wechatConfig['mchid']);

                    try {
                        $checkoutResult = \WxPayApi::refund($input);
                    } catch (\Exception $e) {
                        $fileLog->write('订单退款调用抛异常:' . $e->errorMessage() . '-' . $transaction_id . '-' . $totalFee . '-' . $wechatRefundPrice, 1, RUNTIME_PATH . "Logs/Home/WechatRefund/" . date('Y-m-d') . ".log");
                        $commit = false;
                        $orderRoomModel->rollback();
                        throw new \Exception('500,506', 506);
                        return;
                    }

                    if (!isset($checkoutResult['result_code']) || $checkoutResult['result_code'] != 'SUCCESS') {
                        $fileLog->write('订单退款调用失败:' . $checkoutResult['return_msg'] . '-' . $checkoutResult['err_code'] . '-' . $checkoutResult['err_code_des'] . '-' . $transaction_id . '-' . $totalFee . '-' . $wechatRefundPrice, 1, RUNTIME_PATH . "Logs/Home/WechatRefund/" . date('Y-m-d') . ".log");
                        $commit = false;
                    }
                }
            }

            if ($commit && $aliNeedRefund && $aliRefundPrice != 0.00) {
                // 修改代收记录退款字段
                $checkoutResult = $orderPayInfoModel->saveInfo($orderPayInfo[ORDER_PAY_ALI][0]['id'], $aliRefundPrice);
                if (empty($checkoutResult)) {
                    $commit = false;
                }

                if ($commit) {
                    vendor('Ali.AopClient');
                    vendor('Ali.request.AlipayTradeRefundRequest');

                    $aliConfig = C('ALIPAY_CONFIG');
                    $aop = new \Vendor\Ali\AopClient();
                    $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
                    $aop->appId = $aliConfig['appId'];
                    $aop->rsaPrivateKeyFilePath = '../private/aliPayKey/private_key.pem';
                    $aop->alipayPublicKey='../private/aliPayKey/ali_aes_public_key.pem';
                    $aop->apiVersion = '1.0';
                    $aop->postCharset='UTF-8';
                    $aop->format='json';
                    $request = new \Vendor\Ali\AlipayTradeRefundRequest();
                    $tradeNumber = $orderPayInfo[ORDER_PAY_ALI][0]['tradenumber'];
                    $outRequestNo = $orderPayInfo[ORDER_PAY_ALI][0]['outtrademumber'] . date('YmdHis');
                    $request->setBizContent('{
                        "trade_no":"' . $tradeNumber . '",
                        "refund_amount":' . $aliRefundPrice . ',
                        "refund_reason":"订单退款' . $aliRefundPrice . '元",
                        "out_request_no":"' . $outRequestNo . '"
                    }');

                    try {
                        $checkoutResult = $aop->execute($request);
                    } catch (\Exception $e) {
                        $fileLog->write('订单退款调用抛异常:' . $e->errorMessage() . '-' . $tradeNumber . '-' . $aliRefundPrice, 1, RUNTIME_PATH . "Logs/Home/AliRefund/" . date('Y-m-d') . ".log");
                        $commit = false;
                        $orderRoomModel->rollback();
                        throw new \Exception('500,506', 506);
                        return;
                    }

                    if ($checkoutResult->alipay_trade_refund_response->code != '10000') {
                        $commit = false;
                        $fileLog->write('订单退款调用失败:' . $tradeNumber . '-' . $aliRefundPrice . '-' . $checkoutResult->alipay_trade_refund_response->code . '-' . $checkoutResult->alipay_trade_refund_response->msg . '-' . $checkoutResult->alipay_trade_refund_response->sub_code . '-' . $checkoutResult->alipay_trade_refund_response->sub_msg, 1, RUNTIME_PATH . "Logs/Home/AliRefund/" . date('Y-m-d') . ".log");
                    }
                }
            }
        }

        if ($commit) {
            //发送退房消息服务
            //根据需要退房的用户 查询手机号以及用户名称
            $messageData = array();
            foreach ($orderRoomInfo as $orderRoomId => $orderRoomItem) {
                if (in_array($orderRoomId, $needCheckOutSubOrderIds)) {
                    foreach ($orderRoomItem['user'] as $orderUserItem) {
                        $messageData[] = array(
                            'orderRoomId' => $orderRoomId,
                            'name' => $orderUserItem['name'],
                            'areacode' => $orderUserItem['areacode'],
                            'mobile' => $orderUserItem['mobile'],
                            'roomName' => $orderRoomItem['roominfo_name'],
                            'startdate' => $orderRoomItem['startdate'],
                            'enddate' => $orderRoomItem['checkoutdate']
                        );
                    }
                    unset($orderUserItem);
                }
            }
            unset($orderRoomItem);
            if (!empty($messageData)) {
                $this->pushBackendCardTask($this->backendTaskType['CANCEL'], $hotelId, null, $messageData);
            }
            if ($multiTransMode === false) {
                $orderRoomModel->commit();
            }
            return true;
        } else {
            if ($multiTransMode === false) {
                $orderRoomModel->rollback();
            }
            throw new \Exception('500,506', 506);
            return false;
        }
    }

    /**
     * 为订单办理入住
     * 方法会抛异常
     * @modify trainyao 2016-01-07      创建
     * @modify trainyao  2016-04-11     提前获取房卡
     * @param  integer   $hotelId        客栈id
     * @param  integer   $orderId        父订单id
     * @param  integer   $subOrderIds    办理入住子订单id(s)
     * @param  integer   $from           操作来源
     * @param  string    $orderUserData  子订单入住人变化数据数组[{
     *                                       value=>orderRoomId, users => [{orderUser=> orderuser_id, name=>入住人姓名, mobile=>入住人手机, identity=>身份证}, {}, ...]
     *                                       传入roomId, nights, payment可以办理入住同时改变子订单信息,   传入 roomId, nights 将会前往检查是否存在时间冲突
     *                                       },{}, {}, ...]
     * @param  string    $receipt        入住收款
     * @param  string    $receiptPay     收款方式id
     * @param  string    $deposit        入住收押金
     * @param  string    $depositPay     收押方式id
     * @param  string    $remark         入住备注
     * @param  mixin  $operator          操作人id
     * @return mixin                   执行结果,执行成功返回已入住订单数据
     * @param integer $checkIn  办理入住时 检查该房间当天之前已预订或已入住的房间信息 1：检查 0：不检查
     * @param string $roomIds  办理入住时 房间的Id 如：$roomIds = '178,179';
     * @param string $orderRoomId  orderRoom表的id
     * @param array $vipCard  会员卡数据
     * @param integer $receiptBeforeValue 收款转化前金额
     * @param integer $depositBeforeValue 押金转化前金额
     * @param integer $receiptCurrencyId 收款 货币id
     * @param integer $depositCurrencyId 押金 货币id
     */
    public function checkInOrder($hotelId, $orderId, $subOrderIds, $from, $orderUserData, $receipt = null, $receiptPay = null, $deposit = null, $depositPay = null, $remark = null, $operator = null, $checkIn = 0, $roomIds = '', $orderRoomId = '', $vipCard = null, $receiptBeforeValue = 0, $depositBeforeValue = 0, $receiptCurrencyId = 0, $depositCurrencyId = 0) {
        // 处理传入数据格式
        if (!is_array($subOrderIds)) {
            $subOrderIds = explode(',', $subOrderIds);
        }
        // 检查是否有房间权限限制
        try {
            $orderInfo = $this->getOrderInfo($hotelId, $orderId, true, false);
        } catch (\Exception $e) {
            throw $e;
        }
        $orderRoomInfo = $orderInfo[0]['rooms'];
        if (MODULE_NAME != 'Extend') {
            $adminId = getUserId();
            $adminAuthorityLogic = A('Common/AdminAuthority', 'Logic');
            if (!$adminAuthorityLogic->checkIsAdmin($adminId, $hotelId)) {
                $accountLogic = A('Common/Account', 'Logic');
                $roomAuthority = $accountLogic->getAdminRoomAuthority($adminId, $hotelId);

                // 判断前端传来的房间ID是否都有权限
                if (!empty(array_diff(array_column($orderRoomInfo, 'roominfo_id'), $roomAuthority))) {
                    throw new \Exception('403,202', 202);
                }
            }
        }
        //检查客栈是否启用
        $hotelLogic = A('Common/Hotel', 'Logic');
        $hotelLogic->checkHotelActive($hotelId);
        $hotelLogic->checkHotelStatus($hotelId);

        // 办理入住时 查询该房间当天之前已预订或已入住的房间信息
        if ($checkIn == 1) {
            //不做任何插入或更新 再返回查询结果
            $roomData = ValidateCheckIn($hotelId, $roomIds, $orderRoomId);
            return $roomData;
        }
        // 判断预定人是否变化(第一个子订单的入住人是预定人)
        $bookerChangeData = array();
        $firstOrderRoom = $orderRoomInfo[0];
        $orderUserData = getArrayValueAsIndex($orderUserData, 'value');
        if (!empty($orderUserData[$firstOrderRoom['id']])) {
            $name = $orderUserData[$firstOrderRoom['id']]['users'][0]['name'];
            $areacode = $orderUserData[$firstOrderRoom['id']]['users'][0]['areacode'];
            $mobile = $orderUserData[$firstOrderRoom['id']]['users'][0]['mobile'];
            $identity = $orderUserData[$firstOrderRoom['id']]['users'][0]['identity'];
            $nameOriginal = $firstOrderRoom['user'][0]['name'];
            $areacodeOriginal = $firstOrderRoom['user'][0]['areacode'];
            $mobileOriginal = $firstOrderRoom['user'][0]['mobile'];
            $identityOriginal = $firstOrderRoom['user'][0]['identity'];
            if ($name != $nameOriginal || $mobile != $mobileOriginal || $identity != $identityOriginal || $areacode != $areacodeOriginal) {
                $bookerChangeData['name'] = $name;
                $bookerChangeData['areacode'] = $areacode;
                $bookerChangeData['mobile'] = $mobile;
                $bookerChangeData['identity'] = $identity;
                $bookerChangeData['name_before'] = $nameOriginal;
                $bookerChangeData['areacode_before'] = $areacodeOriginal;
                $bookerChangeData['mobile_before'] = $mobileOriginal;
                $bookerChangeData['identity_before'] = $identityOriginal;
            }
        }
        
        // (入住日期在今天或以前的房间都要一次入住)
        // 检查传进来的是否都可以入住,是否有未传进来的可入住的子订单id
        if ($orderRoomInfo[0]['hour']) {
            $today = time();
        } else {
            $today = strtotime(date('Y-m-d') . ' 00:00:00');
        }

        foreach ($orderRoomInfo as $index => $orderRoom) {
            if (strtotime($orderRoom['startdate']) > $today) {
                unset($orderRoomInfo[$index]);
            }
        }
        unset($orderRoom);

        $orderRoomInfo = getArrayValueAsIndex($orderRoomInfo, 'id');
        $currentSubOrderIds = array_column($orderRoomInfo, 'id');
        if (!empty(array_diff($subOrderIds, $currentSubOrderIds))) {
            // 传进来的有不可操作的订单id
            throw new \Exception('403,502', 502);
        }
        // 检查时间冲突
        $newRoomId = array_values(array_unique(array_column($orderUserData, 'roomId')));
        $needCheckTimeCross = false;
        foreach ($orderUserData as &$orderUserDataItem) {
            if (!isset($orderUserDataItem['roomId']) && !isset($orderUserDataItem['nights'])) {
                $orderUserDataItem['pass'] = true;
            } else {
                $needCheckTimeCross = true;
                $orderUserDataItem['orderRoomId'] = $orderUserDataItem['value'];
                $orderUserDataItem['orderDate'] = substr($orderRoomInfo[$orderUserDataItem['value']]['startdate'], 0, 10);
                $orderUserDataItem['roomId'] = isset($orderUserDataItem['roomId']) ? $orderUserDataItem['roomId'] : $orderRoomInfo[$orderUserDataItem['value']]['roominfo_id'];
                if (isset($orderUserDataItem['month'])) {
                    $orderUserDataItem['nights'] = getNight($orderUserDataItem['orderDate'], date('Y-m-d',strtotime('+' . $orderUserDataItem['month'] . 'months', strtotime($orderUserDataItem['orderDate']))));
                } else {
                    $orderUserDataItem['nights'] = isset($orderUserDataItem['nights']) ? $orderUserDataItem['nights'] : $orderRoomInfo[$orderUserDataItem['value']]['realnight'];
                }
                $orderUserDataItem['hour'] = isset($orderUserDataItem['hour']) ? $orderUserDataItem['hour'] : $orderRoomInfo[$orderUserDataItem['value']]['hour'];
                $orderUserDataItem['month'] = isset($orderUserDataItem['month']) ? $orderUserDataItem['month'] : $orderRoomInfo[$orderUserDataItem['value']]['month'];
                $orderUserDataItem['payment'] = isset($orderUserDataItem['payment']) ? $orderUserDataItem['payment'] : $orderRoomInfo[$orderUserDataItem['value']]['payment'];
            }
        }
        unset($orderUserDataItem);
        if ($needCheckTimeCross) {
            $timeArray = $this->prepareCheckTimeCross($hotelId, $orderUserData);
            $this->checkTimeCross($orderUserData, $timeArray);
        }

        // 获取客栈最迟退房时间
        $hotelLogic = A('Common/Hotel', 'Logic');
        // 获取客栈最迟退房时间 
        $checkinType = $firstOrderRoom['hour'] > 0 ? 1 : 0;
        if ($checkinType === 1) {
            //第一个入住人有hour 就代表钟点房 保存钟点房的type
            $hotelBookDetail = $hotelLogic->getHotelBookingDetail($hotelId, $checkinType);
        } else {
            $hotelBookDetail = $hotelLogic->getHotelBookingDetail($hotelId, $checkinType);
        }
        $hotelCheckoutTime = isset($hotelBookDetail['checkouttime']) ? $hotelBookDetail['checkouttime'] : '12:00';
        $hotelCheckinTime = isset($hotelBookDetail['checkintime']) ? $hotelBookDetail['checkintime'] : '14:00';
        
        $canPreGetCard = date('H') < substr($hotelCheckinTime, 0, 2) ? true : false;
        $canPreGetCardSubOrderIds = array();
        if ($canPreGetCard) {
            // 处理提前入住数据
            $canPreGetCardSubOrders = array();
            foreach ($orderRoomInfo as $orderRoomId => $orderRoomItem) {
                array_push($canPreGetCardSubOrders, array(
                    'roomId' => $orderRoomItem['roominfo_id'],
                    'startdate' => $orderRoomItem['startdate'],
                    'enddate' => $orderRoomItem['enddate'],
                    'orderRoomId' => $orderRoomId,
                ));
            }
            unset($orderRoomItem);
            $canPreGetCardIndex = $this->getCanPreGetCardIndex($hotelId, $canPreGetCardSubOrders);
            foreach ($canPreGetCardIndex as $indexValue) {
                array_push($canPreGetCardSubOrderIds, $canPreGetCardSubOrders[$indexValue]['orderRoomId']);
            }
        }

        // 取出redis中活跃的子订单id,将订单状态由已过期改为已预订
        $outdatedOrdeIds = array();
        foreach ($currentSubOrderIds as $id) {
            if ($orderRoomInfo[$id]['status'] == ORDER_OUTDATED) {
                array_push($outdatedOrdeIds, $id);
            }
        }
        unset($id);
        if (!empty($outdatedOrdeIds)) {
            $orderRoomModel = D('OrderRoom');
            $redisOrderRecordInfo = $orderRoomModel->getInfoInRedisByHotelRoomOrderRoom($hotelId, null, $outdatedOrdeIds);
            if ($redisOrderRecordInfo === false) {
                // redis查询失败
                throw new \Exception('500,506', 506);
            }
            foreach ($redisOrderRecordInfo as $redisOrderRecordItem) {
                $orderRoomInfo[$redisOrderRecordItem['orderroom_id']]['status'] = ORDER_BOOKED;
            }
            unset($redisOrderRecordItem);
        }

        // 检查子订单id是否都是与父订单关联,顺便生成修改信息数组
        // 检查房间,入住晚数,子订单价格是否改变
        $orderRoomRecordArray = array();
        $orderInfoPaymentNew = $orderInfo[0]['payment'];
        $orderInfoPaymentChange = false;
        if (!empty($newRoomId)) {
            $roomLogic = A('Common/Room', 'Logic');
            $roomInfo = $roomLogic->getRoom($hotelId, $newRoomId, true);
            $roomInfo = getArrayValueAsIndex($roomInfo, 'id');
        }
        foreach ($subOrderIds as $id) {
            if (!in_array($id, $currentSubOrderIds)) {
                throw new \Exception('403,202', 202);
            }
            $status = $orderRoomInfo[$id]['status'];
            if ($status == ORDER_BOOKED || $status == ORDER_PAYED) {
                $roomTypeName = $orderRoomInfo[$id]['roomtype_name'];
                $roomInfoName = $orderRoomInfo[$id]['roominfo_name'];
                $orderRoomChange = array(
                    'orderroom_id' => $id,
                    'roomtype_name' => $roomTypeName,
                    'roomtype_name_before' => $roomTypeName,
                    'roominfo_name' => $roomInfoName,
                    'roominfo_name_before' => $roomInfoName,
                    'status_before' => $status,
                    'status' => ORDER_CHECKINED,
                );
                
                // 检查roomId, nights, payment是否修改
                if (isset($orderUserData[$id]['roomId']) || isset($orderUserData[$id]['nights']) || isset($orderUserData[$id]['payment'])) {
                    if ($orderRoomInfo[$id]['roominfo_id'] != $orderUserData[$id]['roomId'] || $orderRoomInfo[$id]['realnight'] != $orderUserData[$id]['nights'] || $orderRoomInfo[$id]['payment'] != $orderUserData[$id]['payment']) {
                        $orderRoomChange['roominfo_id'] = $orderRoomInfo[$id]['roominfo_id'];
                        $orderRoomChange['roominfo_name'] = $orderRoomInfo[$id]['roominfo_name'];
                        $orderRoomChange['roomtype_name'] = $orderRoomInfo[$id]['roomtype_name'];
                        $orderRoomChange['night'] = $orderRoomInfo[$id]['realnight'];
                        $orderRoomChange['realnight'] = $orderRoomInfo[$id]['realnight'];
                        $orderRoomChange['startdate_before'] = $orderRoomInfo[$id]['startdate'];
                        $orderRoomChange['enddate_before'] = $orderRoomInfo[$id]['enddate'];
                        $orderRoomChange['startdate'] = $orderRoomInfo[$id]['startdate'];
                        $orderRoomChange['enddate'] = $orderRoomInfo[$id]['enddate'];
                        $orderRoomChange['checkoutdate'] = $orderRoomInfo[$id]['checkoutdate'];
                        $orderRoomChange['payment'] = $orderRoomInfo[$id]['payment'];
                        $orderRoomChange['payment_before'] = $orderRoomInfo[$id]['payment'];
                        if (isset($orderUserData[$id]['roomId']) && $orderRoomInfo[$id]['roominfo_id'] != $orderUserData[$id]['roomId']) {
                            $orderRoomChange['roominfo_id'] = $orderUserData[$id]['roomId'];
                            $orderRoomChange['roominfo_name'] = $roomInfo[$orderUserData[$id]['roomId']]['name'];
                            $orderRoomChange['roomtype_name'] = $roomInfo[$orderUserData[$id]['roomId']]['roomtype_name'];
                        }
                        if (isset($orderUserData[$id]['nights']) && $orderRoomInfo[$id]['realnight'] != $orderUserData[$id]['nights']) {
                            $orderRoomChange['night'] = $orderUserData[$id]['nights'];
                            $orderRoomChange['realnight'] = $orderUserData[$id]['nights'];
                            $orderRoomChange['enddate'] = getOrderEndTime(substr($orderRoomInfo[$id]['startdate'], 0, 10), $orderUserData[$id]['nights']);
                            $orderRoomChange['checkoutdate'] = $orderRoomChange['enddate'];
                            $orderRoomChange['month'] = $orderUserData[$id]['month'];
                        }

                        if (isset($orderUserData[$id]['hour']) && $orderRoomInfo[$id]['hour'] != $orderUserData[$id]['hour']) {
                            $orderRoomChange['hour'] = $orderUserData[$id]['hour'];
                            $orderRoomChange['enddate'] = getOrderEndTime($orderRoomInfo[$id]['startdate'], $orderUserData[$id]['nights'], $orderUserData[$id]['hour']);
                            $orderRoomChange['checkoutdate'] = $orderRoomChange['enddate'];
                        }

                        if (isset($orderUserData[$id]['payment']) && $orderRoomInfo[$id]['payment'] != $orderUserData[$id]['payment']) {
                            $orderRoomChange['payment'] = $orderUserData[$id]['payment'];
                            $orderRoomChange['payment_before'] = $orderRoomInfo[$id]['payment'];
                            $orderInfoPaymentNew += ((double)$orderRoomChange['payment'] - (double)$orderRoomChange['payment_before']);
                            $orderInfoPaymentChange = true;
                        }
                    }
                }
                array_push($orderRoomRecordArray, $orderRoomChange);
            }
        }
        unset($id);
        // 无需修改的子订单
        if (empty($orderRoomRecordArray)) {
            throw new \Exception('403,202', 202);
        }

        // 判断备注是否变化
        if (!is_null($remark) && $remark != $orderInfo[0]['remark']) {
            $bookerChangeData['remark'] = $remark;
            $bookerChangeData['remark_before'] = $orderInfo[0]['remark'];
        }
        $orderChange = empty($bookerChangeData) ? null : 1;
        $orderChange = empty($receipt) && empty($deposit) && is_null($orderChange) ? null : 1;
        $orderChange = !$orderInfoPaymentChange && is_null($orderChange) ? null : 1;
        $userChange = false;
        // 判断入住人是否变化(前台有传过来时才判断),顺便生成变化数组
        $orderUserChangeData = array();
        foreach ($currentSubOrderIds as $subOrderId) {
            if (in_array($subOrderId, $subOrderIds)) {
                $indexedOrderUser = getArrayValueAsIndex($orderRoomInfo[$subOrderId]['user'], 'orderuser_id');
                $indexedFrontOrderUser = getArrayValueAsIndex($orderUserData[$subOrderId]['users'], 'orderUser');
                foreach ($indexedOrderUser as $orderUserId => $orderUserItem) {
                    if ($orderUserItem['isdelete'] == IS_DELETE || !isset($indexedFrontOrderUser[$orderUserId])) {
                        continue;
                    }

                    $nameOriginal = $orderUserItem['name'];
                    $areacodeOriginal = $orderUserItem['areacode'];
                    $mobileOriginal = $orderUserItem['mobile'];
                    $identityOriginal = $orderUserItem['identity'];
                    $idsexOriginal = $orderUserItem['idsex'];
                    $idnationOriginal = $orderUserItem['idnation'];
                    $idaddressOriginal = $orderUserItem['idaddress'];
                    $name = $indexedFrontOrderUser[$orderUserId]['name'];
                    $areacode = $indexedFrontOrderUser[$orderUserId]['areacode'];
                    $mobile = $indexedFrontOrderUser[$orderUserId]['mobile'];
                    $identity = $indexedFrontOrderUser[$orderUserId]['identity'];
                    if ($userChange || ($nameOriginal != $name || $mobileOriginal != $mobile || $identityOriginal != $identity || $areacodeOriginal != $areacode)) {
                        $userChange = true;
                    }

                    $orderUserChange = array(
                        'orderroom_id' => $subOrderId,
                        'roominfo_id' => $orderRoomInfo[$subOrderId]['roominfo_id'],
                        'userroom_id' => $orderUserItem['userroom_id'],
                        'orderuser_id' => $orderUserId,
                        'name' => $name,
                        'name_before' => $nameOriginal,
                        'areacode' => $areacode,
                        'mobile' => $mobile,
                        'areacode_before' => $areacodeOriginal,
                        'mobile_before' => $mobileOriginal,
                        'identity' => $identity,
                        'identity_before' => $identityOriginal,
                        'idsex' => $idsexOriginal,
                        'idsex_before' => $idsexOriginal,
                        'idnation' => $idnationOriginal,
                        'idnation_before' => $idnationOriginal,
                        'idaddress' => $idaddressOriginal,
                        'idaddress_before' => $idaddressOriginal,
                        'startdate' => $orderRoomInfo[$subOrderId]['startdate'],
                        'enddate' => $orderRoomInfo[$subOrderId]['checkoutdate'],
                    );

                    array_push($orderUserChangeData, $orderUserChange);
                }
                unset($orderUserItem);
                unset($indexedOrderUser);
                unset($indexedFrontOrderUser);
            }
        }
        unset($subOrderId);
        $userChange = $userChange ? 1 : null;

        // 执行修改
        $orderRoomModel = D('OrderRoom');
        if (!$this->getMultiTransMode()) {
            $orderRoomModel->startTrans();
        }
        $commit = true;
        
        // 生成单次操作记录id
        $orderRecordModel = D('OrderRecord');
        $orderRecordId = $orderRecordModel->addInfo($orderId, $from, !$orderInfoPaymentChange ? null : ((double)$orderInfoPaymentNew - (double)$orderInfo[0]['payment']), $orderChange, $userChange, 1, $operator);
        if (empty($orderRecordId)) {
            $commit = false;
        }

        if ($commit) {
            $checkInResult = $this->changeSubOrder($hotelId, $orderId, $orderRecordId, null, $orderRoomRecordArray, null);
            if (!$checkInResult) {
                $commit = false;
            }
        }

        // 更改实际入住时间
        if ($commit) {
            $today = date('Y-m-d H:i:s');
            foreach ($orderRoomRecordArray as $key => $orderRoomItem) {
                $checkInResult = $orderRoomModel->setCheckoutData($orderRoomItem['orderroom_id'], null, null, $today);
                if (!$checkInResult) {
                    $commit = false;
                    break;
                }
            }
            unset($orderRoomItem);
        }

        // 保存订单信息
        $userLoginLogic = A('Common/UserLogin', 'Logic');
        if ($commit && $orderChange) {
            $bookerUserId = null;
            if (!empty($bookerChangeData['mobile'])) {
                $bookerUserId = $userLoginLogic->checkRegister($bookerChangeData['mobile'], true, $bookerChangeData['areacode']);
                $orderInfo[0]['userlogin_id'] = $bookerUserId;
            }
            $depositNew = null;
            if (!empty($deposit)) {
                $depositNew = $deposit + $orderInfo[0]['deposit'];
                $depositNew = $depositNew > 999999.99 ? 999999.99 : $depositNew;
                $orderInfo[0]['deposit'] = $depositNew;
            }
            $receiptNew = null;
            if (!empty($receipt)) {
                $receiptNew = $receipt + $orderInfo[0]['receipt'];
                $receiptNew = $receiptNew > 999999.99 ? 999999.99 : $receiptNew;
                $orderInfo[0]['receipt'] = $receiptNew;
            }
            $bookerChangeData['status'] = 2; 
            $checkInResult = $this->saveOrderInfoChange($hotelId, $orderId, $orderRecordId, null, $depositNew, $orderInfoPaymentChange ? $orderInfoPaymentNew : null, $receiptNew, $bookerUserId, $bookerChangeData);
            if (empty($checkInResult)) {
                $commit = false;
            }
        } else if($commit){
            $orderInfoModel = D('OrderInfo');
            $checkInResult = $orderInfoModel->saveInfo($orderId, null, null, null, null, null, null, null, null, null, 2);
            if (empty($checkInResult)) {
                $commit = false;
            }
        }
        // 保存金额变化
        if ($commit) {
            $receiptRecordArray = array(
                array(
                    'pay' => $receipt,
                    'id' => $receiptPay,
                    'transBeforeValue' => $receiptBeforeValue,
                    'currencyId' => $receiptCurrencyId,
                )
            );
            $depositRecordArray = array(
                array(
                    'pay' => $deposit,
                    'id' => $depositPay,
                    'transBeforeValue' => $depositBeforeValue,
                    'currencyId' => $depositCurrencyId,
                )
            );

            $checkInResult = $this->saveOrderPayChange($hotelId, $orderId, $orderRecordId, $receiptRecordArray, $depositRecordArray);
            if (empty($checkInResult)) {
                $commit = false;
            }
        }

        // 如有会员卡消费 则修改会员卡
        if ($commit && !empty($receipt) && !empty($receiptPay) && !empty($vipCard)) {
            $receives = array(
                array(
                    'category' => PAY_CHANGE_RECEIPT,
                    'type' => $receiptPay,
                    'value' => $receipt,
                ),
            );
            $result = $this->modifyVipUserCard($hotelId, $vipCard['cardMobile'], $vipCard['cardAreaCode'], $receives);
            if ($result == false) {
                $commit = false;
            }
        }

        // 保存入住人变化
        $currentCheckinTime = date('H:i:s');
        if ($commit && !empty($orderUserChangeData)) {
            // 处理入住人数据,查询是否有变化,以及能不能提前拿卡
            foreach ($orderUserChangeData as &$orderUserChange) {
                $userChange = false;
                if ($orderUserChange['name'] != $orderUserChange['name_before'] || $orderUserChange['mobile'] != $orderUserChange['mobile_before'] || $orderUserChange['identity'] != $orderUserChange['identity_before'] || $orderUserChange['areacode'] != $orderUserChange['areacode_before']) {
                    $userChange = true;
                }
                if ($userChange) {
                    if (!empty($orderUserChange['mobile'])) {
                        $userId = $userLoginLogic->checkRegister($orderUserChange['mobile'], true, $orderUserChange['areacode']);
                        if (empty($userId)) {
                            $commit = false;
                            break;
                        }
                    } else {
                        // 如果$orderUserChange['mobile']不为空,情况是手机从有改为无
                        // 手机从改为无,将userlogin_id置为0
                        $userId = 0;
                    }
                } else {
                    // 入住人无变化,不保存userlogin_id
                    $userId = null;
                }
                $orderUserChange['userlogin_id'] = $userId;

                // 查看是否能提前获取房卡,以更新userRoom数据2222
                if ($checkinType === 0) {
                    $checkInCanPreGetCard = $canPreGetCard && in_array($orderUserChange['orderroom_id'], $canPreGetCardSubOrderIds);
                    $orderUserChange['startdate'] = substr($orderUserChange['startdate'], 0, 11) . ($checkInCanPreGetCard ? $currentCheckinTime : $hotelCheckinTime);
                    $orderUserChange['enddate'] = substr($orderUserChange['enddate'], 0, 11) . $hotelCheckoutTime;
                } 

                // 如果入住人没变,提前房卡时间没变,不进行userRoom修改
                if (!$userChange && !$checkInCanPreGetCard) {
                    unset($orderUserChange['userroom_id']);
                }
            }
            unset($orderUserChange);
            if ($commit) {
                $checkInResult = $this->saveOrderUserChange($hotelId, $orderId, $orderRecordId, null, $orderUserChangeData, null);
                if (empty($checkInResult)) {
                    $commit = false;
                }
            }
        }

        // 如该订单有使用优惠券 则修改优惠券已使用
        $userCouponModel = D('UserCoupon');
        $userCouponData = $userCouponModel->getUserCouponByOrderId($orderId);
        if ($commit && !empty($userCouponData)) {
            $saveResult = $userCouponModel->saveUserCouponOrderId($userCouponData['id'], null, USER_COUPON_USED);
            if ($saveResult === false) {
                $commit = false;
            }
        }

        if ($commit) {
            if (!$this->getMultiTransMode()) {
                $orderRoomModel->commit();
            }
            if (!empty($bookerChangeData['name'])) {
                $orderInfo[0]['name'] = $bookerChangeData['name'];
            }
            if (!empty($bookerChangeData['areacode'])) {
                $orderInfo[0]['areacode'] = $bookerChangeData['areacode'];
            }
            if (!empty($bookerChangeData['mobile'])) {
                $orderInfo[0]['mobile'] = $bookerChangeData['mobile'];
            }
            if (!empty($bookerChangeData['identity'])) {
                $orderInfo[0]['identity'] = $bookerChangeData['identity'];
            }
            if (!empty($bookerChangeData['remark'])) {
                $orderInfo[0]['remark'] = $bookerChangeData['remark'];
            }
            //发送短信消息通知
            $needUpdateUsers = array();
            foreach ($orderUserData as $orderUser) {
                $orderRoomItem = $orderRoomInfo[$orderUser['value']];
                //钟点房
                if ($checkinType===1) {
                    foreach ($orderUser['users'] as $frontOrderUserItem) {
                        $needUpdateUsers[] = array(
                            'orderRoomId' => $orderUser['value'],
                            'name' => $frontOrderUserItem['name'],
                            'areacode' => $frontOrderUserItem['areacode'],
                            'mobile' => $frontOrderUserItem['mobile'],
                            'roomName' => $orderRoomItem['roominfo_name'],
                            'startdate' => $orderRoomItem['startdate'],
                            'enddate' => $orderRoomItem['checkoutdate'],
                        );
                    }
                    unset($frontOrderUserItem);
                } else { 
                    $startDateCheckinTime = $canPreGetCard && in_array($orderUser['value'], $canPreGetCardSubOrderIds) ? $currentCheckinTime : $hotelCheckinTime;
                    foreach ($orderUser['users'] as $frontOrderUserItem) {
                        $needUpdateUsers[] = array(
                            'orderRoomId' => $orderUser['value'],
                            'name' => $frontOrderUserItem['name'],
                            'areacode' => $frontOrderUserItem['areacode'],
                            'mobile' => $frontOrderUserItem['mobile'],
                            'roomName' => $orderRoomItem['roominfo_name'],
                            'startdate' => substr($orderRoomItem['startdate'], 0, 11) . $startDateCheckinTime,
                            'enddate' => substr($orderRoomItem['checkoutdate'], 0, 11) . $hotelCheckoutTime,
                        );
                    }
                    unset($frontOrderUserItem);
                }
               
            }
            unset($orderUser);
            $this->pushBackendCardTask($this->backendTaskType['ADD'], $hotelId, null, $needUpdateUsers, $from===ORDER_CHANGE_BOOK_WEB?true:false);

            // 修改该退房而未退房的子订单状态  status = 6
            if (!empty($orderRoomInfo)) {
                $orderRoomInfo = $this->modifyOrderRoomStatus(array_values($orderRoomInfo));
                $orderRoomInfo = getArrayValueAsIndex($orderRoomInfo, 'id');
            }
            return array(
                'order' => $orderInfo[0],
                'suborder' => $orderRoomInfo,
            );
        } else {
            if (!$this->getMultiTransMode()) {
                $orderRoomModel->rollback();
                throw new \Exception('500,506', 506);
            } else {
                return false;
            }
        }
    }

    /**
     * 修改订单信息变化记录
     * @modify trainyao 2016-01-16       创建
     * @param  integer   $hotelId         客栈id,修改父订单可不传
     * @param  integer   $orderId         订单id,新建父订单不传
     * @param  integer   $orderRecordId         订单记录id
     * @param  integer   $hotelChannelId  客栈渠道id
     * @param  string   $depositNew      押金变化后值
     * @param  string   $paymentNew      支付金额变化后值
     * @param  stinrg   $receiptNew      已收款变化后值
     * @param  integer   $userId          预定人id
     * @param  array   $changeDataArray 变化记录数组
     *                                  hotelchannel_id, remark, mobile, name, identity
     *                                  hotelchannel_before, remark_before, mobile_before, name_before, identity_before,
     * @return boolean                    执行结果
     */
    private function saveOrderInfoChange($hotelId, $orderId, $orderRecordId, $hotelChannelId, $depositNew, $paymentNew, $receiptNew, $userId, $changeDataArray = null) {
        $orderInfoModel = D('OrderInfo');
        if (!empty($paymentNew)) {
            $paymentNew = keepNumberInRange($paymentNew);
        }
        if (!empty($depositNew)) {
            $depositNew = keepNumberInRange($depositNew);
        }
        if (!empty($receiptNew)) {
            $receiptNew = keepNumberInRange($receiptNew);
        }
        $newOrderId = 0;
        if (empty($orderId)) {
            $saveResult = $orderInfoModel->addInfo($hotelId, $hotelChannelId, $depositNew, $paymentNew, $receiptNew, $userId, $changeDataArray['mobile'], $changeDataArray['name'], $changeDataArray['identity'], $changeDataArray['remark'], $changeDataArray['status'], $changeDataArray['orig'],$changeDataArray['discount'],$changeDataArray['discountrule'], $changeDataArray['areacode']);
        } else {
            $mobileSave = isset($changeDataArray['mobile']) ? $changeDataArray['mobile'] : null;
            $mobileAreacode = isset($changeDataArray['areacode']) ? $changeDataArray['areacode'] : null;
            $nameSave = isset($changeDataArray['name']) ? $changeDataArray['name'] : null;
            $identitySave = isset($changeDataArray['identity']) ? $changeDataArray['identity'] : null;
            $remarkSave = isset($changeDataArray['remark']) ? $changeDataArray['remark'] : null;
            $charityPrice = isset($changeDataArray['charityPrice']) ? $changeDataArray['charityPrice'] : null;
            $saveResult = $orderInfoModel->saveInfo($orderId, $hotelChannelId, $depositNew, $paymentNew, $receiptNew, $userId, $mobileSave, $nameSave, $identitySave, $remarkSave, $changeDataArray['status'], $changeDataArray['orig'], $mobileAreacode, $charityPrice);
        }
        if (!$saveResult) {
            return false;
        } else {
            $newOrderId = $saveResult;
        }

        if (!is_null($changeDataArray)) {
            // 保存订单信息变化记录
            $orderInfoRecordModel = D('OrderInfoRecord');
            $hotelchannel = isset($changeDataArray['hotelchannel_id']) ? $changeDataArray['hotelchannel_id'] : null;
            $remark = isset($changeDataArray['remark']) ? $changeDataArray['remark'] : null;
            $areaCode = isset($changeDataArray['areacode']) ? $changeDataArray['areacode'] : '86';
            $mobile = isset($changeDataArray['mobile']) ? $changeDataArray['mobile'] : null;
            $name = isset($changeDataArray['name']) ? $changeDataArray['name'] : null;
            $identity = isset($changeDataArray['identity']) ? $changeDataArray['identity'] : null;
            $hotelchannelBefore = isset($changeDataArray['hotelchannel_before']) ? $changeDataArray['hotelchannel_before'] : null;
            $remarkBefore = isset($changeDataArray['remark_before']) ? $changeDataArray['remark_before'] : null;
            $areaCodeBefore = isset($changeDataArray['areacode_before']) ? $changeDataArray['areacode_before'] : '86';
            $mobileBefore = isset($changeDataArray['mobile_before']) ? $changeDataArray['mobile_before'] : null;
            $nameBefore = isset($changeDataArray['name_before']) ? $changeDataArray['name_before'] : null;
            $identityBefore = isset($changeDataArray['identity_before']) ? $changeDataArray['identity_before'] : null;

            $saveResult = $orderInfoRecordModel->addInfo($orderRecordId, $hotelchannel, $remark, $mobile, $name, $identity, $hotelchannelBefore, $remarkBefore, $mobileBefore, $nameBefore, $identityBefore, $areaCode, $areaCodeBefore);
            if (!$saveResult) {
                return false;
            }
        }
        // 返回父订单id
        if (empty($orderId)) {
            return $newOrderId;
        }
        return true;
    }

    /**
     * 增加删除修改子订单逻辑抽取
     * @modify trainyao 2016-02-02         创建
     * @modify zhangzhen 2017-03-14         是否需要修改父订单信息
     * @param  integer   $hotelId           客栈id
     * @param  integer   $orderId           父订单id
     * @param  integer   $orderRecordId     订单记录id
     * @param  array    $orderRoomToAdd    array( 符合orderRoom格式
     *                                         'roominfo_id', 'creator', 'night', 'realnight'
     *                                         'startdate','enddate','checkoutdate',roomtype_name','roominfo_name','payment','status'
     *                                     )
     * @param  array    $orderRoomToEdit   !!!!!需要修改订单,传入roominfo_id字段, 需要修改订单状态传入status_before,status(status_before,status不相等)字段!!!!!!
     *                                     array( 符合orderRoomRecord格式与orderRoomModel格式
     *                                         'status'(必传)
     *                                         'orderroom_id'
     *                                         'startdate','enddate','roomtype_name','roominfo_name','payment'
     *                                         'startdate_before','enddate_before','roomtype_name_before','roominfo_name_before','payment_before','status_before'
     *                                          需要修改子订单信息传'roominfo_id', 此时'orderroom_id', 'payment', 'startdate', 'enddate', 'roomtype_name', 'roominfo_name', 'night', 'checkoutdate', 'realnight'必传,否则会导致子订单信息写入报错或者写成空
     *                                     )
     * @param  array    $orderRoomToDelete array( 符合orderRooomRecord格式  !!!!!需要修改订单(如实际入住晚数),传入checkoutdate字段!!!!!!
     *                                         'orderroom_id'
     *                                         'startdate_before','enddate_before','roomtype_name_before','roominfo_name_before','payment_before','status_before'
     *                                         'checkoutdate', 'realnight'
     *                                     )
     * @param  boolean    $needToChangeFather   是否需要修改父订单
     * @param  array    $orderCheckRoomRecords   查房操作记录
     * @return bool
     */

    private function changeSubOrder($hotelId, $orderId, $orderRecordId, $orderRoomToAdd, $orderRoomToEdit, $orderRoomToDelete, $needToChangeFather = null, $orderCheckRoomRecords = null) {
        $orderRoomModel = D('OrderRoom');
        $orderRoomRecords = array();
        $roomNoToUpdateBatchNo = array();
        // 生成修改订单的orderRoomRecord
        if (!empty($orderRoomToEdit)) {
            $orderRoomToEdit = getArrayValueAsIndex($orderRoomToEdit, 'status', 'multiStruct');
            foreach ($orderRoomToEdit as $status => $orderRooms) {
                // 如果办理退房或者取消订单，记录房间号用来增加
                if (in_array($status, array(ORDER_CHECKOUTED, ORDER_CANCELED))) {
                    $roomNoToUpdateBatchNo = array_merge($roomNoToUpdateBatchNo, array_column($orderRooms, 'roominfo_name_before'));
                }
                $orderRoomIds = array();
                foreach ($orderRooms as $orderRoom) {
                    // 判断是否需要更新批次号
                    if (isset($orderRoom['roominfo_name']) && isset($orderRoom['roominfo_name_before']) && $orderRoom['roominfo_name'] != $orderRoom['roominfo_name_before']) {
                        array_push($roomNoToUpdateBatchNo, $orderRoom['roominfo_name_before']);
                    }

                    // 判断是否需要修改订单信息
                    if (isset($orderRoom['roominfo_id'])) {
                        $changeResult = $orderRoomModel->saveInfo($hotelId, $orderRoom['orderroom_id'], $orderId, $orderRoom['roominfo_id'], $orderRoom['payment'], $orderRoom['startdate'], $orderRoom['enddate'], $orderRoom['roomtype_name'], $orderRoom['roominfo_name'], $orderRoom['night'], $orderRoom['checkoutdate'], $orderRoom['realnight'], $orderRoom['roominfo_from'], $orderRoom['hour'], $orderRoom['month']);
                        if (empty($changeResult)) {
                            return false;
                        }
                    }
                    // 判断是否需要修改订单状态
                    if (isset($orderRoom['status_before']) && $orderRoom['status'] != $orderRoom['status_before']) {
                        array_push($orderRoomIds, $orderRoom['orderroom_id']);
                    }

                    array_push($orderRoomRecords, array(
                        'orderrecord_id' => $orderRecordId,
                        'payment_before' => isset($orderRoom['payment_before']) ? $orderRoom['payment_before'] : 0.00,
                        'startdate_before' => isset($orderRoom['startdate_before']) ? $orderRoom['startdate_before'] : '0000-00-00 00:00:00',
                        'enddate_before' => isset($orderRoom['enddate_before']) ? $orderRoom['enddate_before'] : '0000-00-00 00:00:00',
                        'roomtype_name_before' => isset($orderRoom['roomtype_name_before']) ? $orderRoom['roomtype_name_before'] : '',
                        'roominfo_name_before' => isset($orderRoom['roominfo_name_before']) ? $orderRoom['roominfo_name_before'] : '',
                        'status_before' => isset($orderRoom['status_before']) ? $orderRoom['status_before'] : 0,
                        'payment' => isset($orderRoom['payment']) ? $orderRoom['payment'] : 0.00,
                        'startdate' => isset($orderRoom['startdate']) ? $orderRoom['startdate'] : '0000-00-00 00:00:00',
                        'enddate' => isset($orderRoom['enddate']) ? $orderRoom['enddate'] : '0000-00-00 00:00:00',
                        'roomtype_name' => isset($orderRoom['roomtype_name']) ? $orderRoom['roomtype_name'] : '',
                        'roominfo_name' => isset($orderRoom['roominfo_name']) ? $orderRoom['roominfo_name'] : '',
                        'status' => isset($orderRoom['status']) ? $orderRoom['status'] : 0,
                        'type' => ORDER_CHANGE_EDIT,
                    ));
                }
                unset($orderRoom);

                if (!empty($orderRoomIds)) {
                    $changeResult = $orderRoomModel->setStatus($orderRoomIds, $status);
                    if (empty($changeResult)) {
                        return false;
                    }
                }
            }
            unset($orderRooms);
        }
        unset($orderRoomToEdit);
        // 生成增加订单,删除订单的orderRoomRecord
        if (!empty($orderRoomToAdd) || !empty($orderRoomToDelete)) {
            if (!empty($orderRoomToAdd)) {
                foreach ($orderRoomToAdd as &$orderRoomInfo) {
                    $orderRoomInfo['orderinfo_id'] = $orderId;
                    $orderRoomInfo['hotelentity_id'] = $hotelId;
                    $orderRoomInfo['createtime'] = date('Y-m-d H:i:s');

                    array_push($orderRoomRecords, array(
                        'orderrecord_id' => $orderRecordId,
                        'payment_before' => 0.00,
                        'startdate_before' => '0000-00-00 00:00:00',
                        'enddate_before' => '0000-00-00 00:00:00',
                        'roomtype_name_before' => '',
                        'roominfo_name_before' => '',
                        'status_before' => 0,
                        'payment' => $orderRoomInfo['payment'],
                        'startdate' => $orderRoomInfo['startdate'],
                        'enddate' => $orderRoomInfo['enddate'],
                        'roomtype_name' => $orderRoomInfo['roomtype_name'],
                        'roominfo_name' => $orderRoomInfo['roominfo_name'],
                        'status' => $orderRoomInfo['status'],
                        'type' => ORDER_CHANGE_ADD,
                    ));
                }
                unset($orderRoomInfo);
            }
            if (!empty($orderRoomToDelete)) {
                //父订单减去子订单的款项
                $subPayment = 0;
                // 保存房间号增加批次号
                $roomNoToUpdateBatchNo = array_merge($roomNoToUpdateBatchNo, array_column($orderRoomToDelete, 'roominfo_name_before'));
                foreach ($orderRoomToDelete as $orderRoomInfo) {
                    // 执行取消订单时的修改订单操作
                    if (isset($orderRoomInfo['checkoutdate'])) {
                        $changeResult = $orderRoomModel->setCheckoutData($orderRoomInfo['orderroom_id'], $orderRoomInfo['checkoutdate'], $orderRoomInfo['realnight']);
                        if (empty($changeResult)) {
                            return false;
                        }
                    }
                    array_push($orderRoomRecords, array(
                        'orderrecord_id' => $orderRecordId,
                        'payment_before' => isset($orderRoomInfo['payment_before']) ? $orderRoomInfo['payment_before'] : 0.00,
                        'startdate_before' => isset($orderRoomInfo['startdate_before']) ? $orderRoomInfo['startdate_before'] : '0000-00-00',
                        'enddate_before' => isset($orderRoomInfo['enddate_before']) ? $orderRoomInfo['enddate_before'] : '0000-00-00',
                        'roomtype_name_before' => isset($orderRoomInfo['roomtype_name_before']) ? $orderRoomInfo['roomtype_name_before'] : '',
                        'roominfo_name_before' => isset($orderRoomInfo['roominfo_name_before']) ? $orderRoomInfo['roominfo_name_before'] : '',
                        'status_before' => $orderRoomInfo['status_before'],
                        'payment' => 0.00,
                        'startdate' => '0000-00-00 00:00:00',
                        'enddate' => '0000-00-00 00:00:00',
                        'roomtype_name' => '',
                        'roominfo_name' => '',
                        'status' => ORDER_CANCELED,
                        'type' => ORDER_CHANGE_DELETE,
                    ));
                    //记录已预订的子订单的款项
                    if($orderRoomInfo['status_before'] == ORDER_BOOKED){
                        $orderPayment = $orderRoomModel->getPayment($orderRoomInfo['orderroom_id']);
                        $subPayment += $orderPayment['payment'];
                    }
                }
                unset($orderRoomInfo);
            }
        }
        // 批次号加一
        if (!empty($roomNoToUpdateBatchNo)) {
            $roomNoToUpdateBatchNo = array_values(array_unique($roomNoToUpdateBatchNo));
            // 检查房间是否同步,存在同步房间才前往调用RPC接口,进行批次号加一
            $roomInfoModel = D('RoomInfo');
            $notSyncRoomNos = $roomInfoModel->getInfoByHotel($hotelId,[ROOMFROM_MEIZHU,ROOMFROM_OTHER]);
            $notSyncRoomNos = array_column($notSyncRoomNos, 'name');
            if (!empty($notSyncRoomNos)) {
                $roomNoToUpdateBatchNo = array_diff($roomNoToUpdateBatchNo, $notSyncRoomNos);
            }

            if (!empty($roomNoToUpdateBatchNo)) {
                // 获取客栈同步锁掌柜集群号
                $hotelLogic = A('Common/Hotel', 'Logic');
                $hotelInfo = $hotelLogic->getHotelByHotelId(array($hotelId));
                if (!empty($hotelInfo[0]['communityno'])) {
                    Vendor('phpRPC.phprpc_client');
                    $client = new \PHPRPC_Client(C('MANAGE_QRCODE_URL'));
                    $client->setEncryptMode(3);
                    $data = array(
                        'flag' => 'uclbrt',
                        'time' => time(),
                        'communityNo' => $hotelInfo[0]['communityno'],
                        'batchNo' => time(),
                        'room' => array_values($roomNoToUpdateBatchNo),
                    );
                    $result = $client->updateBatchNo($data);
                    $result = json_decode($result, true);
                    if (!is_array($result) || $result['httpstatus'] != 200) {
                        return false;
                    }
                }
            }
        }

        // 添加子订单记录操作历史
        $orderRoomAddAllId = null;
        if (!empty($orderRoomToAdd)) {
            $changeResult = $orderRoomModel->addInfo($orderRoomToAdd);
            if (!$changeResult) {
                return false;
            }
            $orderRoomAddAllId = $changeResult;
        }

        // 删除子订单
        if (!empty($orderRoomToDelete)) {
            $changeResult = $orderRoomModel->setStatus(array_column($orderRoomToDelete, 'orderroom_id'), ORDER_CANCELED);
            if($changeResult && $subPayment != 0 && $needToChangeFather === true) {
                $orderInfoModel = D('OrderInfo');
                $orderInfo = $orderInfoModel->getInfo($orderId, false);
                $orig = $subPayment = $orderInfo['orig'] - $subPayment;
                //是否是会员
                if(!empty( (float)$orderInfo['discountrule']) ){
                    if($orderInfo['discount'] === '0'){
                        $subPayment = $subPayment * ($orderInfo['discountrule'] / 10);
                    }
                    if($orderInfo['discount'] === '1'){
                        $subPayment = $subPayment - $orderInfo['discountrule'];
                    }
                    $subPayment = $subPayment < 0 ? 0 : $subPayment;
                }
                $changeResult = $orderInfo = $orderInfoModel->saveInfo($orderId, null, null, $subPayment, null, null, null, null, null, null, null, $orig);

            }
            if (!$changeResult) {
                return false;

            }
        }
        // 添加订单操作记录
        if (!empty($orderRoomRecords)) {
            $orderRoomRecordModel = D('OrderRoomRecord');
            $changeResult = $orderRoomRecordModel->addInfo($orderRoomRecords);
            if (!$changeResult) {
                return false;
            }
        }

        // 添加查房操作记录
        if (!empty($orderCheckRoomRecords)) {
            $orderRoomCheckRecordModel = D('OrderRoomCheckRecord');
            $changeResult = $orderRoomCheckRecordModel->addInfo($orderCheckRoomRecords);
            if (!$changeResult) {
                return false;
            }
        }

        if (!empty($orderRoomToAdd)) {
            return $orderRoomAddAllId;
        }
        return true;
    }

    /**
     * 保存订单入住人变化
     * @modify trainyao 2016-04-20         创建
     * @param  integer   $hotelId           客栈ID
     * @param  intege   $orderId           订单id
     * @param  integer   $orderRecordId     订单记录id
     * @param  array   $orderUserToAdd    订单入住人增加信息数组 {orderroom_id(起始新增的订单id), data=>[[{ !!!两层数组,表示一个子订单的多个同住人,没处理完一个子订单,子订单ID++
     *                                            userlogin_id, roominfo_id, startdate, enddate
     *                                            name, mobile, identity, isdelete
     *                                        }, {}, ...], [], ...]} array(
     * @param  array   $orderUserToEdit   订单入住人修改信息数组 array(
     *                                        userlogin_id (必须带)
     *                                        userroom_id, orderroom_id, roominfo_id, startdate, enddate (入住时间,userlogin_id没该可以不带)
     *                                        orderuser_id, name, name_before, mobile, mobile_before, identity, identity_before (必须带)
     *                                    )
     * @param  array   $orderUserToDelete 订单入住人删除信息数组 array(
     *                                        orderuser_id => array() 要删除的orderUserId
     *                                        userroom_id  => array() 要删除的userRoomId
     *                                        data         => array(name_before, mobile_before, identity_before)
     *                                    )
     * @param  array   $orderUserToAddWhileEdit 修改已存在的子订单时,增加入住人 [{orderroom_id, mobile, name, identity, startdate, enddate, roominfo_id, userlogin_id, isdelete}, {},...]
     * @return boolean                      执行结果
     */
    private function saveOrderUserChange($hotelId, $orderId, $orderRecordId, $orderUserToAdd = null, $orderUserToEdit = null, $orderUserToDelete = null, $orderUserToAddWhileEdit = null) {
        $orderUserModel = D('OrderUser');
        $userRoomModel = D('UserRoom');
        $orderUserRecordData = array();
        if (!empty($orderUserToAdd) || !empty($orderUserToAddWhileEdit)) {
            // 初始化orderUser数据 userRoom数据
            $orderUserData = array();
            $userRoomData = array();
            if (!empty($orderUserToAdd)) {
                $orderRoomId = $orderUserToAdd['orderroom_id'];
                foreach ($orderUserToAdd['data'] as $orderUserToAddItems) {
                    foreach ($orderUserToAddItems as $key => $orderUserToAddItem) {
                        array_push($orderUserData, array(
                            'orderinfo_id' => $orderId,
                            'userlogin_id' => $orderUserToAddItem['userlogin_id'],
                            'name' => $orderUserToAddItem['name'],
                            'areacode' => $orderUserToAddItem['areacode'],
                            'mobile' => $orderUserToAddItem['mobile'],
                            'identity' => $orderUserToAddItem['identity'],
                            'idsex' => $orderUserToAddItem['idsex'],
                            'idnation' => $orderUserToAddItem['idnation'],
                            'idaddress' => $orderUserToAddItem['idaddress'],
                            'isdelete' => isset($orderUserToAddItem['isdelete']) ? $orderUserToAddItem['isdelete'] : NOT_DELETE,
                        ));
                        array_push($userRoomData, array(
                            'userlogin_id' => $orderUserToAddItem['userlogin_id'],
                            'orderroom_id' => $orderRoomId,
                            'roominfo_id' => $orderUserToAddItem['roominfo_id'],
                            'startdate' => $orderUserToAddItem['startdate'],
                            'enddate' => $orderUserToAddItem['enddate'],
                            'isdelete' => isset($orderUserToAddItem['isdelete']) ? $orderUserToAddItem['isdelete'] : NOT_DELETE,
                        ));
                        array_push($orderUserRecordData, array(
                            'orderrecord_id' => $orderRecordId,
                            'name' => $orderUserToAddItem['name'],
                            'areacode' => $orderUserToAddItem['areacode'],
                            'mobile' => $orderUserToAddItem['mobile'],
                            'identity' => $orderUserToAddItem['identity'],
                            'idsex' => $orderUserToAddItem['idsex'],
                            'idnation' => $orderUserToAddItem['idnation'],
                            'idaddress' => $orderUserToAddItem['idaddress'],
                            'areacode_before' => '',
                            'name_before' => '',
                            'mobile_before' => '',
                            'identity_before' => '',
                            'idsex_before' => '',
                            'idnation_before' => '',
                            'idaddress_before' => '',
                            'type' => ORDER_CHANGE_ADD,
                        ));
                    }
                    unset($orderUserToAddItem);
                    $orderRoomId++;
                }
                unset($orderUserToAddItems);
            }
            if (!empty($orderUserToAddWhileEdit)) {
                foreach ($orderUserToAddWhileEdit as $orderUserToAddItem) {
                    array_push($orderUserData, array(
                        'orderinfo_id' => $orderId,
                        'userlogin_id' => $orderUserToAddItem['userlogin_id'],
                        'name' => $orderUserToAddItem['name'],
                        'areacode' => $orderUserToAddItem['areacode'],
                        'mobile' => $orderUserToAddItem['mobile'],
                        'identity' => $orderUserToAddItem['identity'],
                        'idsex' => $orderUserToAddItem['idsex'],
                        'idnation' => $orderUserToAddItem['idnation'],
                        'idaddress' => $orderUserToAddItem['idaddress'],
                        'isdelete' => isset($orderUserToAddItem['isdelete']) ? $orderUserToAddItem['isdelete'] : NOT_DELETE,
                    ));
                    array_push($userRoomData, array(
                        'userlogin_id' => $orderUserToAddItem['userlogin_id'],
                        'orderroom_id' => $orderUserToAddItem['orderroom_id'],
                        'roominfo_id' => $orderUserToAddItem['roominfo_id'],
                        'startdate' => $orderUserToAddItem['startdate'],
                        'enddate' => $orderUserToAddItem['enddate'],
                        'isdelete' => isset($orderUserToAddItem['isdelete']) ? $orderUserToAddItem['isdelete'] : NOT_DELETE,
                    ));
                    array_push($orderUserRecordData, array(
                        'orderrecord_id' => $orderRecordId,
                        'name' => $orderUserToAddItem['name'],
                        'areacode' => $orderUserToAddItem['areacode'],
                        'mobile' => $orderUserToAddItem['mobile'],
                        'identity' => $orderUserToAddItem['identity'],
                        'idsex' => $orderUserToAddItem['idsex'],
                        'idnation' => $orderUserToAddItem['idnation'],
                        'idaddress' => $orderUserToAddItem['idaddress'],
                        'areacode_before' => '',
                        'name_before' => '',
                        'mobile_before' => '',
                        'identity_before' => '',
                        'idsex_before' => '',
                        'idnation_before' => '',
                        'idaddress_before' => '',
                        'type' => ORDER_CHANGE_ADD,
                    ));
                }
                unset($orderUserToAddItem);
            }

            // 增加orderUser数据
            $changeResult = $orderUserModel->addInfo($orderUserData);
            if (empty($changeResult)) {
                return false;
            }

            // 更新userRoom数据
            $orderUserId = $changeResult;
            foreach ($userRoomData as &$userRoomDataItem) {
                $userRoomDataItem['orderuser_id'] = $orderUserId;
                $orderUserId++;
            }
            unset($userRoomDataItem);

            // 增加userRoom数据
            $changeResult = $userRoomModel->addInfo($userRoomData);
            if (empty($changeResult)) {
                return false;
            }
        }

        if (!empty($orderUserToEdit)) {
            foreach ($orderUserToEdit as $orderUserToEditItem) {
                // 修改orderUser
                if (isset($orderUserToEditItem['orderuser_id'])) {
                    $changeResult = $orderUserModel->saveInfo($orderUserToEditItem['orderuser_id'], $orderId, $orderUserToEditItem['userlogin_id'], $orderUserToEditItem['mobile'], $orderUserToEditItem['name'], $orderUserToEditItem['identity'], $orderUserToEditItem['areacode'], $orderUserToEditItem['idsex'], $orderUserToEditItem['idnation'], $orderUserToEditItem['idaddress']);
                    if (empty($changeResult)) {
                        return false;
                    }
                }

                // 修改userRoom
                if (isset($orderUserToEditItem['userroom_id'])) {
                    $changeResult = $userRoomModel->saveInfo($orderUserToEditItem['userroom_id'], $orderUserToEditItem['userlogin_id'], $orderUserToEditItem['orderroom_id'], $orderUserToEditItem['roominfo_id'], $orderUserToEditItem['startdate'], $orderUserToEditItem['enddate']);
                    if (empty($changeResult)) {
                        return false;
                    }
                }
                // 生成入住人修改记录
                if ($orderUserToEditItem['name'] != $orderUserToEditItem['name_before'] || $orderUserToEditItem['mobile'] != $orderUserToEditItem['mobile_before'] || $orderUserToEditItem['identity'] != $orderUserToEditItem['identity_before'] || $orderUserToEditItem['areacode'] != $orderUserToEditItem['areacode_before']) {
                    array_push($orderUserRecordData, array(
                        'orderrecord_id' => $orderRecordId,
                        'name' => $orderUserToEditItem['name'],
                        'areacode' => $orderUserToEditItem['areacode'],
                        'mobile' => $orderUserToEditItem['mobile'],
                        'identity' => $orderUserToEditItem['identity'],
                        'idsex' => $orderUserToEditItem['idsex'],
                        'idnation' => $orderUserToEditItem['idnation'],
                        'idaddress' => $orderUserToEditItem['idaddress'],
                        'areacode_before' => $orderUserToEditItem['areacode_before'],
                        'name_before' => $orderUserToEditItem['name_before'],
                        'mobile_before' => $orderUserToEditItem['mobile_before'],
                        'identity_before' => $orderUserToEditItem['identity_before'],
                        'idsex_before' => $orderUserToEditItem['idsex_before'],
                        'idnation_before' => $orderUserToEditItem['idnation_before'],
                        'idaddress_before' => $orderUserToEditItem['idaddress_before'],
                        'type' => ORDER_CHANGE_EDIT,
                    ));
                }
            }
            unset($orderUserToEditItem);
        }

        if (!empty($orderUserToDelete)) {
            // 删除orderUser
            $changeResult = $orderUserModel->deleteInfo($orderUserToDelete['orderuser_id']);
            if (empty($changeResult)) {
                return false;
            }
            // 删除userRoom
            $changeResult = $userRoomModel->deleteInfo($orderUserToDelete['userroom_id']);
            if (empty($changeResult)) {
                return false;
            }

            // 生成入住人修改记录
            foreach ($orderUserToDelete['data'] as $orderUserToDeleteItem) {
                array_push($orderUserRecordData, array(
                    'orderrecord_id' => $orderRecordId,
                    'name' => '',
                    'areacode' => '',
                    'mobile' => '',
                    'identity' => '',
                    'idsex' => '',
                    'idnation' => '',
                    'idaddress' => '',
                    'areacode_before' => $orderUserToDeleteItem['areacode_before'],
                    'name_before' => $orderUserToDeleteItem['name_before'],
                    'mobile_before' => $orderUserToDeleteItem['mobile_before'],
                    'identity_before' => $orderUserToDeleteItem['identity_before'],
                    'idsex_before' => $orderUserToDeleteItem['idsex_before'],
                    'idnation_before' => $orderUserToDeleteItem['idnation_before'],
                    'idaddress_before' => $orderUserToDeleteItem['idaddress_before'],
                    'type' => ORDER_CHANGE_DELETE,
                ));
            }
            unset($orderUserToDeleteItem);
        }

        if (!empty($orderUserRecordData)) {
            $orderUserRecordModel = D('OrderUserRecord');
            $changeResult = $orderUserRecordModel->addInfo($orderUserRecordData);
            if (empty($changeResult)) {
                return false;
            }
        }

        return true;
    }

    /**
     * 为每个子订单补充父订单信息
     * @modify trainyao 2016-01-08 创建
     * @param  integer   $hotelId 客栈id
     * @param  array   $orderRoom 子订单信息
     * @param  array   $orderInfo 父订单信息,有传入的话可以直接使用
     * @return array              子订单信息
     */
    private function fillOrderInfo($hotelId, $orderRoom, $orderInfo = null) {
        if (empty($orderInfo)) {
            $orderIds = array_column($orderRoom, 'orderinfo_id');
            $orderInfoModel = D('OrderInfo');
            $orderInfo = $orderInfoModel->getInfo($orderIds, false);
            if (count($orderIds) == 1) {
                $orderInfo = array($orderInfo);
            }
        }
        if (!is_null($hotelId)) {
            $orderInfo = $this->fillChannelInfo($hotelId, $orderInfo);
        }
        $orderInfo = getArrayValueAsIndex($orderInfo, 'id');

        foreach ($orderRoom as &$orderRoomInfoItem) {
            $orderRoomInfoItem['order'] = $orderInfo[$orderRoomInfoItem['orderinfo_id']];
        }
        unset($orderRoomInfoItem);

        return $orderRoom;
    }

    /**
     * 补充子订单入住人信息
     * @modify trainyao 2016-01-19      创建
     * @param  integer   $hotelId        客栈id
     * @param  array   $orderRoom       子订单信息
     * @param  mixin   $orderUserInfos 已取出的子订单入住人信息
     * @param  mixin   $userRoomInfos  已取出的入住人房间信息
     * @return array                   子订单信息
     */
    public function fillOrderUserInfo($hotelId, $orderRoom, $orderUserInfos = null, $userRoomInfos = null) {
        if (empty($orderUserInfos)) {
            $orderInfoIds = array_column($orderRoom, 'orderinfo_id');
            // 获取订单入住人信息
            $orderUserModel = D('OrderUser');
            $orderUserInfos = $orderUserModel->getInfoByOrder($orderInfoIds);
        }
        if (empty($userRoomInfos)) {
            $orderUserIds = array_column($orderUserInfos, 'id');
            $userRoomModel = D('UserRoom');
            $userRoomInfos = $userRoomModel->getInfosByOrderUser($orderUserIds);
        }
        $userRoomInfos = getArrayValueAsIndex($userRoomInfos, 'orderroom_id', 'multi');
        $orderUserInfos = getArrayValueAsIndex($orderUserInfos, 'id');
        // 补充信息
        foreach ($orderRoom as &$orderRoomItem) {
            $orderUserId = $userRoomInfos[$orderRoomItem['id']][0]['orderuser_id'];
            $orderRoomItem['name'] = $orderUserInfos[$orderUserId]['name'];
            $orderRoomItem['areacode'] = $orderUserInfos[$orderUserId]['areacode'];
            $orderRoomItem['mobile'] = $orderUserInfos[$orderUserId]['mobile'];
            $orderRoomItem['identity'] = $orderUserInfos[$orderUserId]['identity'];
            $orderRoomItem['user'] = array();
            foreach ($userRoomInfos[$orderRoomItem['id']] as $userRoomItem) {
                array_push($orderRoomItem['user'], array(
                    'name' => $orderUserInfos[$userRoomItem['orderuser_id']]['name'],
                    'areaCode' => $orderUserInfos[$userRoomItem['orderuser_id']]['areacode'],
                    'mobile' => $orderUserInfos[$userRoomItem['orderuser_id']]['mobile'],
                    'identity' => $orderUserInfos[$userRoomItem['orderuser_id']]['identity'],
                    'userLoginId' => $orderUserInfos[$userRoomItem['orderuser_id']]['userlogin_id'],
                ));
            }
            unset($userRoomItem);
        }
        unset($orderRoomItem);
        return $orderRoom;
    }

    /**
     * 补充父订单渠道信息
     * @modify trainyao 2016-01-09 创建
     * @param  integer   $hotelId   客栈id
     * @param  array   $orderInfo   父订单信息数组
     * @return array                父订单信息数组
     */
    protected function fillChannelInfo($hotelId, $orderInfo) {
        $hotelLogic = A('Common/Hotel', 'Logic');
        $channelInfo = $hotelLogic->getHotelChannel($hotelId);
        $channelInfo = getArrayValueAsIndex($channelInfo, 'id');

        foreach ($orderInfo as &$orderItem) {
            $orderItem['channelName'] = $channelInfo[$orderItem['hotelchannel_id']]['name'];
        }
        unset($orderItem);

        return $orderInfo;
    }

    /**
     * 保存订单金额变化逻辑抽取
     * @modify trainyao 2016-01-15          创建
     * @param  integer   $hotelId           客栈id
     * @param  integer   $orderId           订单id
     * @param  integer   $orderRecordId      订单记录id
     * @param  array   $receiptChangeArray 收款变化记录数据  [{id=>(支付方式id),pay=>(金额,带正负)},{},..]
     * @param  array   $depositChangeArray 押金变化记录数据  [{id=>(支付方式id),pay=>(金额,带正负)},{},..]
     * @param  array   $orderPayRecordChangeArray 支付记录变化数据 执行 save() [{id=>(支付记录表id),...},{},..]
     * @param  integer   $vipUserId 会员id
     * @return boolean                     执行结果
     */
    private function saveOrderPayChange($hotelId, $orderId, $orderRecordId, $receiptChangeArray, $depositChangeArray, $orderPayRecordChangeArray = null, $vipUserId = '0') {
        $orderPayRecordModel = D('OrderPayRecord');
        $orderPayRecordData = array();
        $userId = getUserId();
        if (!empty($receiptChangeArray)) {
            foreach ($receiptChangeArray as $receipt) {
                if (!empty($receipt['pay'])) {
                    $type = isset($receipt['category']) ? $receipt['category'] : (($receipt['pay'] >= 0) ? PAY_CHANGE_RECEIPT : PAY_CHANGE_REFUND);
                    array_push($orderPayRecordData,
                            array(
                        'orderrecord_id' => $orderRecordId,
                        'hotelpay_id' => $receipt['id'],
                        //'type' => ($receipt['pay'] >= 0) ? PAY_CHANGE_RECEIPT : PAY_CHANGE_REFUND,
                        'type' => $type,
                        'pay' => abs($receipt['pay']),
                        'firstpay' => abs($receipt['pay']),
                        'creator' => $userId,
                        'orderinfo_id' => $orderId,
                        'hotelentity_id' => $hotelId,
                        'createtime' => date('Y-m-d H:i:s'),
                        'vipuser_id' => $vipUserId,
                        'trans_before_pay' => abs($receipt['transBeforeValue']),
                        'currency_id' => $receipt['currencyId'],
                    ));
                }
            }
            unset($receiptChangeArray);
        }
        if (!empty($depositChangeArray)) {
            foreach ($depositChangeArray as $deposit) {
                if (!empty($deposit['pay'])) {
                    array_push($orderPayRecordData,
                            array(
                        'orderrecord_id' => $orderRecordId,
                        'hotelpay_id' => $deposit['id'],
                        'type' => ($deposit['pay'] >= 0) ? PAY_CHANGE_DEPOSIT : PAY_CHANGE_DEPOSIT_BACK,
                        'pay' => abs($deposit['pay']),
                        'firstpay' => abs($deposit['pay']),
                        'creator' => $userId,
                        'orderinfo_id' => $orderId,
                        'hotelentity_id' => $hotelId,
                        'createtime' => date('Y-m-d H:i:s'),
                        'vipuser_id' => $vipUserId,
                        'trans_before_pay' => abs($deposit['transBeforeValue']),
                        'currency_id' => $deposit['currencyId'],
                    ));
                }
            }
            unset($depositChangeArray);
        }
        if (!empty($orderPayRecordChangeArray)) {
            // 执行修改
            foreach ($orderPayRecordChangeArray as $key => $orderPayRecordChangeArrayItem) {
                $saveResult = $orderPayRecordModel->saveInfo($orderPayRecordChangeArrayItem['id'], $orderPayRecordChangeArrayItem['hotelPayId'], $orderPayRecordChangeArrayItem['type'], $orderPayRecordChangeArrayItem['pay'], $vipUserId, $orderPayRecordChangeArrayItem['trans_before_pay'], $orderPayRecordChangeArrayItem['transCurrencyId']);
                if ($saveResult === false) {
                    return false;
                }
            }
            unset($orderPayRecordChangeArrayItem);

            return true;
        }

        if (empty($orderPayRecordData)) {
            return true;
        }

        $saveResult = $orderPayRecordModel->addInfo($orderPayRecordData);
        if (empty($saveResult)) {
            return false;
        }
        return true;
    }

    /**
     * 保存支付记录变化逻辑抽取
     * @modify wenhui 2017-10-12          创建
     * @param  array   $orderPayRecordChangeArray  [{'orderrecord_id' => 1,'hotelpay_id' => 2,'type' => 3 ...},{}...]
     * @return boolean                     执行结果
     */
    private function saveOrderPayRecordChange($orderRecordId, $orderPayRecordChangeData) {
        $orderPayRecordInfoModel = D('OrderPayRecordInfo');
        if (!empty($orderPayRecordChangeData)) {
            foreach ($orderPayRecordChangeData as $key => &$orderPayRecordChangeItem) {
                $orderPayRecordChangeItem['orderrecord_id'] = $orderRecordId;
            }
            $saveResult = $orderPayRecordInfoModel->addInfo($orderPayRecordChangeData);
            if (empty($saveResult)) {
                return false;
            }
        }

        return true;
    }

    /**
     *
     * @param date $startDate   入住开始时间
     * @param date $endDate 入住结束时间
     * @param integer $type 操作类型  1=添加订单 2=直接入住 3=补录订单
     * @param integer $latestCheckoutTime          客栈最迟退房时间
     * @return type
     */
    protected function getOrderStatus($startDate, $endDate, $type, $status, $latestCheckoutTime = null, $checkinType = 0 , $hoteldiffTimeType = 0) {
        $time = strtotime(substr($startDate,0,10)) - strtotime(date('Y-m-d'));
        //比较今天时间点
        if ($time > 0) {
            $flag = 'future'; //未来时间点
        } else {
            $time2 = strtotime(substr($endDate,0,10)) - strtotime(date('Y-m-d'));
            if ($time2 > 0) {
                $flag = 'cross'; //时间交叉
            } elseif ($time2 == 0) {
                $flag = 'today';
            } else {
                $flag = 'passed'; // 已过期时间
            }
        }
        switch ($type) {
            case 1:
                if (($flag == 'future') || ($flag == 'cross')) {
                    return $status;
                } else if ($flag == 'today') {
                    if (date('H:i') >= $latestCheckoutTime && $checkinType == 0) {
                        return ORDER_CHECKOUTED;
                    }
                    if ($checkinType) {
                        return $status;
                    }
                    if ($hoteldiffTimeType) {
                        return $status;
                    }

                    return ORDER_CHECKINED;
                } else {
                    return ORDER_CHECKOUTED;
                }
                break;
            case 3:
                if (($flag == 'future') || ($flag == 'cross')) {
                    return $status;
                } else if ($flag == 'today') {
                    if (date('H:i') >= $latestCheckoutTime) {
                        return ORDER_CHECKOUTED;
                    }
                    if ($hoteldiffTimeType) {
                        return $status;
                    }
                    return ORDER_CHECKINED;
                } else {
                    return ORDER_CHECKOUTED;
                }
                break;
            case 2: //直接入住
                if (($flag == 'future')) {
                    return $status;
                } else if (($flag == 'cross')) {
                    return ORDER_CHECKINED;
                } else if (($flag == 'today')) {
                    if (date('H:i') >= $latestCheckoutTime && $checkinType == 0) {
                        return ORDER_CHECKOUTED;
                    } else {
                        return ORDER_CHECKINED;
                    }
                } else {
                    return ORDER_CHECKOUTED;
                }
                break;
        }
    }

    public function getHotelOrderPayInfoByDate($hotelId, $startDate, $endDate, $pageIndex, $pageSize) {
        return $this->__singleGet('_getHotelOrderPayInfoByDate', array($hotelId, $startDate, $endDate, $pageIndex, $pageSize));
    }

    /**
     * 根据时间获取客栈的订单支付记录
     * @modify trainyao 2016-01-20 创建
     * @modify trainyao 2016-07-01 增加房间权限限制
     * @param  integer   $hotelId   客栈id
     * @param  string   $startDate 开始时间 Y-m-d
     * @param  string   $endDate   结束时间 Y-m-d
     * @param  integer   $pageIndex   分页页码
     * @param  integer   $pageSize   分页每页长度
     * @return array              支付记录信息数组
     */
    protected function _getHotelOrderPayInfoByDate($hotelId, $startDate, $endDate, $pageIndex = null, $pageSize = null) {
        $orderPayRecordModel = D('OrderPayRecord');
        $orderPayRecordInfos = $orderPayRecordModel->getInfoByHotel($hotelId, $startDate . ' 00:00:00', $endDate . ' 23:59:59');

        // 支付方式
        $hotelLogic = A('Common/Hotel', 'Logic');
        $payResource = $hotelLogic->getHotelPay($hotelId, true, null, true);
        $payResource = getArrayValueAsIndex($payResource, 'id');
        // 获取其他消费项目
        $otherCostResource = $hotelLogic->getHotelOtherCost($hotelId, true);
        $otherCostResource = getArrayValueAsIndex($otherCostResource, 'id');
        // 获取分销渠道
        $channelResource = $hotelLogic->getHotelChannel($hotelId);
        $channelResource = getArrayValueAsIndex($channelResource, 'id');
        // 父订单信息
        $orderInfoIds = array_column($orderPayRecordInfos, 'orderinfo_id');
        $orderInfoIds = array_unique($orderInfoIds);
        
        // 检查操作者是否子管理员,若是,需要根据房间权限过滤父订单
        if (MODULE_NAME != 'Extend' && !empty($orderPayRecordInfos)) {
            // 获取房间权限权限
            $adminId = getUserId();
            $adminAuthorityLogic = A('Common/AdminAuthority', 'Logic');

            if (!$adminAuthorityLogic->checkIsAdmin($adminId, $hotelId)) {
                $accountLogic = A('Common/Account', 'Logic');
                $roomAuthority = $accountLogic->getAdminRoomAuthority($adminId, $hotelId);
                if (empty($roomAuthority)) {
                    $orderPayRecordInfos = array();
                } else {
                    // 删除无房间权限的父订单的收款记录
                    $orderRoomModel = D('OrderRoom');
                    $orderRooms = $orderRoomModel->getInfoByOrder($orderInfoIds);
                    // 过滤出有权限的子订单,再过滤出有权限的父订单
                    $orderRooms = fliterArrayByKey($orderRooms, 'roominfo_id', $roomAuthority);
                    $orderInfoIds = array_column($orderRooms, 'orderinfo_id');
                    $orderPayRecordInfos = fliterArrayByKey($orderPayRecordInfos, 'orderinfo_id', $orderInfoIds);
                    // 获取父订单信息
                    $orderInfoModel = D('OrderInfo');
                    $orderInfos = $orderInfoModel->getInfo($orderInfoIds, false);
                    if (count($orderInfoIds) == 1) {
                        $orderInfos = array($orderInfos);
                    }
                    $orderInfos = getArrayValueAsIndex($orderInfos, 'id');
                }
            } else {
                $orderInfoModel = D('OrderInfo');
                $orderInfos = $orderInfoModel->getInfo($orderInfoIds, false);
                if (count($orderInfoIds) == 1) {
                    $orderInfos = array($orderInfos);
                }
                $orderInfos = getArrayValueAsIndex($orderInfos, 'id');
            } 
        }

        // 操作人信息
        if (!empty($orderPayRecordInfos)) {
            $userIds = array_column($orderPayRecordInfos, 'creator');
            $userIds = array_unique($userIds);
            $adminLoginLogic = A('Common/AdminLogin', 'Logic');
            $userInfos = $adminLoginLogic->getInfo($userIds);
            if (count($userIds) == 1) {
                $userInfos = array($userInfos);
            }
            $userInfos = getArrayValueAsIndex($userInfos, 'id');

            // 补充支付方式名字,操作人,订单来源,备注
            foreach ($orderPayRecordInfos as &$orderPayRecordInfo) {
                $hotelPayId = $orderPayRecordInfo['hotelpay_id'];
                $type = $orderPayRecordInfo['type'];
                $orderId = $orderPayRecordInfo['orderinfo_id'];
                $channelId = $orderInfos[$orderId]['hotelchannel_id'];
                if ($hotelPayId == 0) {
                    // 其他消费项目 待收款
                    $orderPayRecordInfo['payname'] = $this->payChangeTypeMap[LANG_SET][PAY_CHANGE_RECEIVABES];
                    $orderPayRecordInfo['typename'] = $otherCostResource[$type]['name'];
                } else {
                    // 0=收款 1= 押金 2=退款 3=退押金 168以上是其他消费项目id  tb_hotel_other_cost.id
                    if (in_array($type, [0,1,2,3])) {
                        $orderPayRecordInfo['typename'] = $this->payChangeTypeMap[LANG_SET][$type];
                    } else {
                        $orderPayRecordInfo['typename'] = $otherCostResource[$type]['name'];
                    }
                    $orderPayRecordInfo['payname'] = $payResource[$hotelPayId]['name'];
                }

                $orderPayRecordInfo['remark'] = $orderInfos[$orderId]['remark'];
                $orderPayRecordInfo['creatorname'] = $userInfos[$orderPayRecordInfo['creator']]['name'];
                $orderPayRecordInfo['channelname'] = $channelResource[$channelId]['name'];
            }
            unset($orderPayRecordInfo);
        }

        if (empty($pageIndex) || empty($pageSize)) {
            return $orderPayRecordInfos;
        }

        return createPageInfo($orderPayRecordInfos, $pageIndex, $pageSize);
    }

    /**
     * 根据传入的数据,获取在时间区间,获取时间区间内客栈所有子订单
     * @modify trainyao 2016-01-23  创建
     * @param  integer   $hotelId    客栈id
     * @param  array   $orderDetails 传进来的参数
     * @return array               checkTimeCross用到的信息数组
     */
    private function prepareCheckTimeCross($hotelId, $orderDetails) {
        // 查找数据库,获取数据库内信息数组
        $dbExistOrderRoom = array();
        $orderRoomModel = D('OrderRoom');
        $isHourOrder = $orderDetails[0]['hour'] ? true : false;
        $roomIds = array_column($orderDetails, 'roomId');
        $roomIds = array_unique($roomIds);
        $orderRooms = $orderRoomModel->getInfoByHotelRoom($hotelId, $roomIds, array(ORDER_BOOKED, ORDER_PAYED, ORDER_CHECKINED, ORDER_CHECKOUTED, ORDER_CANCELED, ORDER_OUTDATED));

        // 统计过期子订单ID,获取redis订单,将有效已过期订单转为已预订
        $orderRooms = getArrayValueAsIndex($orderRooms, 'id');
        $outDateOrderRoomIds = array();
        foreach ($orderRooms as $orderRoomItem) {
            if ($orderRoomItem['status'] == ORDER_OUTDATED) {
                array_push($outDateOrderRoomIds, $orderRoomItem['id']);
            }
        }
        unset($orderRoomItem);

        if (!empty($outDateOrderRoomIds)) {
            $orderRoomModel = D('OrderRoom');
            $redisOrderRecordInfo = $orderRoomModel->getInfoInRedisByHotelRoomOrderRoom($hotelId, null, $outDateOrderRoomIds);
            if ($redisOrderRecordInfo === false) {
                // redis查询失败
                throw new \Exception('500,506', 506);
            }
            foreach ($redisOrderRecordInfo as $redisOrderRecordItem) {
                $orderRooms[$redisOrderRecordItem['orderroom_id']]['status'] = ORDER_BOOKED;
            }
            unset($redisOrderRecordItem);
        }
        //查找出已退房的房间号
        $waitToDeletedOrder = [];
        foreach ($orderDetails as $k1 => $orderDetail) {
            foreach ($orderRooms as $k2 => $orderRoom) {
                if ($orderRoom['id'] == $orderDetail['orderRoomId']&& $orderRoom['status'] == 3) {
                    array_push($waitToDeletedOrder,$orderRoom['roominfo_id']);
                }
            }
        }
        // 用数据库内的数据生成预处理数据,为校验订单冲突准备
        foreach ($orderRooms as $index => $orderRoom) {
            //已退房补录信息，不检查该房间重复
            if (in_array($orderRoom['roominfo_id'], $waitToDeletedOrder)){
                unset($orderRooms[$index]);
                continue;
            }
            // 过期订单或者无实际入住订单,删掉
            if ($orderRoom['realnight'] == 0 && $orderRoom['hour'] == 0 || $orderRoom['status'] == ORDER_OUTDATED || $orderRoom['status'] == ORDER_CANCELED) {
                unset($orderRooms[$index]);
                continue;
            }
            if ($isHourOrder && $orderRoom['status'] == ORDER_CHECKOUTED) {
                unset($orderRooms[$index]);
                continue;
            } 
            if (! $isHourOrder && $orderRoom['status'] == ORDER_CHECKOUTED && isBetweenTime(time(), $orderRoom['startdate'], $orderRoom['checkoutdate'])){
                unset($orderRooms[$index]);
                continue;
            }
            if (! $isHourOrder && $orderRoom['status'] == ORDER_CHECKOUTED && $orderRoom['hour'] != 0) {
                unset($orderRooms[$index]);
                continue;
            }
            // 过滤当天凌晨下的已退房的订单
            if ($orderRoom['status'] == ORDER_CHECKOUTED && $orderRoom['ismidnightorder'] == 1 && date('Y-m-d', strtotime($orderRoom['enddate'])) >= date('Y-m-d')) {
                unset($orderRooms[$index]);
                continue;
            }

            $startDate = strtotime($orderRoom['startdate']);
            $endDate = strtotime($orderRoom['checkoutdate']);
            $dbExistOrderRoom[$orderRoom['roominfo_id']][$startDate] = array(
                'order' => $orderRoom['id'],
                'end' => $endDate,
                'status' => $orderRoom['status'],
            );
        }
        unset($orderRoom);
        return $dbExistOrderRoom;
    }

    /**
     * 检查传入参数是否有时间
     * 方法会抛异常
     * @modify trainyao 2016-01-14    创建
     * @param  array   $orderDetails 前台传入参数 [{pass(!pass=true时,当作没传这组数据), orderDate(YYYY-mm-dd), nights, roomId, orderRoomId(已存在订单校验时间是否冲突需要传该字段)}, {}, {}....],
     * @param  array   $timeArray       已存在的时间数据,判断时要确保不与之重复
     * @return boolean 是否存在时间交叉
     */
    private function checkTimeCross($orderDetails, $timeArray = null) {
        if (empty($timeArray)) {
            $timeArray = array();
        }
        foreach ($orderDetails as $index => $orderDetail) {
            if (!isset($orderDetail['pass']) || !$orderDetail['pass']) {
                $startTime = getOrderStartTime($orderDetail['orderDate']);
                $endTime = getOrderEndTime($orderDetail['orderDate'], $orderDetail['nights'],$orderDetail['hour']);
                $roomId = $orderDetail['roomId'];
                if (empty($timeArray[$roomId])) {
                    $timeArray[$roomId] = array(
                        strtotime($startTime) => array('end' => strtotime($endTime)),
                    );
                } else {
                    if (isset($orderDetail['orderRoomId'])) {
                        $orderRoomId = $orderDetail['orderRoomId'];
                    } else {
                        $orderRoomId = null;
                    }
                    $orderDate = substr($orderDetail['orderDate'], 0, 11);
                    $tempEnd = strtotime($orderDate . '23:59:59');
                    if ($orderDetail['hour'] > 0 && strtotime($startTime) < $tempEnd) {
                        $tempStart = strtotime($orderDate . '00:00:00');
                        foreach ($timeArray[$roomId] as $timestamp => $roomInfo) {
                            //1.当天开始时间<已存在的订单时间
                            //2.已存在的订单时间<当天结束时间
                            //3.订单状态为预订状态
                            //4.预订的房间 != 已存在房间
                            if($tempStart < $timestamp && $timestamp < $tempEnd && $roomInfo['status'] = ORDER_CHECKINED && $orderDetail['orderRoomId'] != $roomInfo['order']) {
                                throw new \Exception('403,500', 500);
                                return false;
                            }
                        }
                    }
                    $timeArray[$roomId] = checkTimeCross($timeArray[$roomId], strtotime($startTime), strtotime($endTime), $orderRoomId);
                    if ($timeArray[$roomId] == false) {
                        throw new \Exception('403,500', 500);
                        return false;
                        break;
                    }
                }
            }
        }
        unset($orderDetail);
        return true;
    }


    /**
    * 预定时检查开始结束时间是否存在交叉
    * @modify trainyao 2016-01-14 创建
    * @param  array   $timeArray 时间数组,array($startTime => $endTime, $startTime2 => $endTime2)
    * @param  string   $startTime 开始时间
    * @param  string   $endTime   结束时间
    * @param  integer   $orderRoomId   子订单id,新增订单时该值为null
    * @return mixin               无交叉返回新时间数组,有交叉返回false
    */
    private function bookCheckTimeCross($timeArray, $startTime, $endTime) {
        ksort($timeArray);
        $startTimes = array_keys($timeArray);
        $endTimes = array_values($timeArray);
        // 找出开始时间在众多开始时间内的顺序
        $number = array_search($startTime, $startTimes);
        $preIndex = $number-1;
        $nxtIndex = $number+1;
        // 判断是否被前一个时间交集到
        if ($preIndex >= 0 && !empty($endTimes[$preIndex]['end']) && $endTimes[$preIndex]['end'] > $startTime) {
            return false;
        }

        // 判断是否交集到后一个时间
        if (!empty($startTimes[$nxtIndex]) && $endTime > $startTimes[$nxtIndex]) {
            return false;
        }

        return true;
    }


    /**
     * 根据子订单数据,筛选出哪些子订单可以提前入住
     * @modify trainyao 2016-04-08 创建
     * @param  integer   $hotelId 客栈ID
     * @param  array   $subOrders 子订单数据  [{roomId, startdate(YYYY-mm-dd HH:ii:ss), enddate(YYYY-mm-dd HH:ii:ss),orderRoomId}, {}, {}...]
     * @return array              可提前入住的索引数组
     */
    public function getCanPreGetCardIndex($hotelId, $subOrders) {
        $todayDate = date('Y-m-d') . ' 00:00:00';
        $canPreGetCardRoomIdToIndex = array();
        // 找出入住时间是今天的子订单,保存其索引与数据
        foreach ($subOrders as $index => $subOrder) {
            if ($subOrder['startdate'] == $todayDate) {
                $canPreGetCardRoomIdToIndex[$subOrder['roomId']] = array(
                    'index' => $index,
                    'data' => $subOrder,
                );
                unset($subOrders[$index]);
            }
        }
        unset($subOrder);
        if (empty($canPreGetCardRoomIdToIndex)) {
            return array();
        }

        // 去除传入子订单中有同一房间id,退房时间是今天的订单
        foreach ($subOrders as $index => $subOrder) {
            if ($subOrder['enddate'] == $todayDate && isset($canPreGetCardRoomIdToIndex[$subOrder['roomId']])) {
                unset($canPreGetCardRoomIdToIndex[$subOrder['roomId']]);
            }
        }
        unset($subOrder);
        if (empty($canPreGetCardRoomIdToIndex)) {
            return array();
        }

        // 查找数据库中房间id,是否有 退房时间是今天的订单
        $orderRoomModel = D('OrderRoom');
        $orderRooms = $orderRoomModel->getInfoByRoomDate($hotelId, array_keys($canPreGetCardRoomIdToIndex), null, $todayDate);
        foreach ($orderRooms as $orderRoom) {
            // 前面的是有效订单(已预订支付入住,且入住晚数不等于0),
            $isActiveSubOrder = in_array($orderRoom['status'], array(ORDER_BOOKED, ORDER_PAYED, ORDER_CHECKINED)) && $orderRoom['realnight'] != 0;
            // 如果前面的订单是自己(修改订单的情况),判断为不是有效订单
            if ($isActiveSubOrder && isset($canPreGetCardRoomIdToIndex[$orderRoom['roominfo_id']])) {
                $isActiveSubOrder = $isActiveSubOrder && ($orderRoom['id'] == $canPreGetCardRoomIdToIndex[$orderRoom['roominfo_id']]['data']['orderRoomId'] ? false : true);
            }
            if (isset($canPreGetCardRoomIdToIndex[$orderRoom['roominfo_id']]) && $isActiveSubOrder && $orderRoom['ismidnightorder'] != 1) {
                unset($canPreGetCardRoomIdToIndex[$orderRoom['roominfo_id']]);
            }
        }

        return array_column($canPreGetCardRoomIdToIndex, 'index');
    }

    /**
     * 修改该退房而未退房的子订单状态  status = 6
     * @modify wenhui 2017-12-05
     * @param array $orderRoom
     */
    public function modifyOrderRoomStatus($orderRoom) {
        // 获取客栈最迟退房时间
        $hotelLogic = A('Common/Hotel', 'Logic');
        $hotelInfo = $hotelLogic->getHotelBookingDetail($orderRoom[0]['hotelentity_id']);
        foreach ($orderRoom as $key => &$orderRoomItem) {
            if (in_array($orderRoomItem['status'], [ORDER_CHECKINED])) {
                // 钟点房
                if ($orderRoomItem['hour'] > 0) {
                    if ($orderRoomItem['enddate']  < date('Y-m-d H:i:s')) {
                        $orderRoomItem['status'] = ORDER_SHOULD_CHECKOUT;
                    }
                } else {
                    $checkoutTime = substr($orderRoomItem['enddate'], 0, 11) . $hotelInfo['checkouttime'] . ':00';
                    if ($checkoutTime < date('Y-m-d H:i:s')) {
                        $orderRoomItem['status'] = ORDER_SHOULD_CHECKOUT;
                    }
                }
            }
        }
        return $orderRoom;
    }

    /**
     * 过滤查找条件
     * @modify songanwei 2016-02-02
     * @param type $orderRoom
     * @param type $search
     */
    private function filterSearch($orderRoom, $search) {
        foreach ($orderRoom as $key => &$orderRoomItem) {
            if (strpos($orderRoomItem['name'], $search) === false) {
                unset($orderRoom[$key]);
            }
        }
        return $orderRoom;
    }

    /**
     * 检查订单是否在客栈内
     * 方法不会抛异常
     * @modify trainyao 2016-05-17   创建
     * @param  mixin   $orderRoomId 子订单id(s)
     * @param  integer   $hotelId     客栈ID
     * @return boolean                是否在客栈内
     */
    public function checkSubOrderInHotel($orderRoomId, $hotelId) {
        $orderRoomModel = D('OrderRoom');
        $orderRoomInfos = $orderRoomModel->getInfo($orderRoomId);
        if (empty($orderRoomInfos)) {
            return false;
        }

        foreach ($orderRoomInfos as $orderRoomInfo) {
            if ($orderRoomInfo['hotelentity_id'] != $hotelId) {
                return false;
            }
        }
        unset($orderRoomInfo);
        return true;
    }

    /**
     * 检查父订单是否在客栈内
     * @modify trainyao 2016-08-16 创建
     * @param  integer   $hotelId   客栈ID
     * @param  mixin   $orderId   父订单id(s)
     * @return boolean              是否在客栈内
     */
    public function checkOrderInHotel($hotelId, $orderId) {
        if (!is_array($orderId)) {
            $orderId = explode(',', $orderId);
        }

        $orderInfoModel = D('OrderInfo');
        $orderInfo = $orderInfoModel->getInfo($orderId);
        if (count($orderId) == 1) {
            $orderInfo = array($orderInfo);
        }

        return empty(array_diff(array_values(array_unique(array_column($orderInfo, 'hotelentity_id'))), array($hotelId)));
    }

    /**
     * 入住订单重发短信
     * @modify AmosZhong 2016-08-08  创建
     * @param  string or integer   $hotelId     客栈ID
     * @param  integer   $orderRoomId 子订单id,必须传一个id
     * @param  integer   $orderUserId 同住人ID,必须传一个id
     * @return boolean                是否在客栈内
     */
    public function resendCheckInOrderSMS($hotelId, $orderRoomId, $orderUserId) {
        if (!is_numeric($orderRoomId)) {
            throw new \Exception('403,501', 501);
        }
        $orderRoomModel = D('OrderRoom');
        $orderRoomInfos = $orderRoomModel->getInfo($orderRoomId);
        if (empty($orderRoomInfos)) {
            throw new \Exception('403,501', 501);
        }

        // 查询
        $orderRoomFound = false;
        foreach ($orderRoomInfos as $orderRoomInfo) {
            if ($orderRoomInfo['hotelentity_id'] == $hotelId) {
                $orderRoomFound = $orderRoomInfo;
            }
        }
        // 找不到订单记录
        if (empty($orderRoomFound)) {
            throw new \Exception('403,501', 501);
        }

        // 获取同住人信息
        $orderUserModel = D('OrderUser');
        $orderUserInfo = $orderUserModel->getInfoByOrder($orderRoomFound['orderinfo_id']);
        if (!in_array($orderUserId, array_column($orderUserInfo, 'id'))) {
            throw new \Exception('403,202', 202);
            return false;
        }
        $orderUserInfo = getArrayValueAsIndex($orderUserInfo, 'id');
        if (empty($orderUserInfo[$orderUserId]['mobile'])) {
            throw new \Exception('403,504', 504);
            return false;
        }
        // 补充信息
        $orderRoomFound['name'] = $orderUserInfo[$orderUserId]['name'];
        $orderRoomFound['areacode'] = $orderUserInfo[$orderUserId]['areacode'];
        $orderRoomFound['mobile'] = $orderUserInfo[$orderUserId]['mobile'];
        $orderRoomFound['identity'] = $orderUserInfo[$orderUserId]['identity'];


        // 订单不是入住状态
        if ($orderRoomFound['status'] != ORDER_CHECKINED) {
            throw new \Exception('403,505', 505);
        }
        $checkinType = $orderRoomFound['hour'] > 0 ? 1 : 0;

        // 检查redis发送短信
        if (empty($this->redisUtil)) {
            $this->redisUtil = new \Org\Util\RedisHelper(null, null, 'meizhu');
        }
        $this->redisUtil->db(C('REDIS_HOME_DB'))->table('orderRoomSendMobile');
        $sendTimesItem = $this->redisUtil->hMGet($orderRoomFound['orderinfo_id']);
        if (!empty($sendTimesItem)) {
            $sendTimes = $sendTimesItem['times'];
            if ($sendTimes >= 3) {
                throw new \Exception('403,507', 507);
            }
            $sendTimes++;
        } else {
            // 设置次数
            $sendTimes = 1;
        }
        
        if ($checkinType === 1) {
            $enddate = $orderRoomFound['enddate'];
            // 订单已成过期的入住订单，无法再开门，所以也不能重发
            if (strtotime($enddate) <= time()) {
                throw new \Exception('403,506', 506);
            }
            $orderRoomFound['startTime'] = $orderRoomFound['startdate'];
            $orderRoomFound['endTime'] = $orderRoomFound['enddate'];
        } else {
            // 获取客栈最迟退房时间
            $hotelLogic = A('Common/Hotel', 'Logic');
            $hotelBookDetail = $hotelLogic->getHotelBookingDetail($hotelId);
            $hotelCheckoutTime = isset($hotelBookDetail['checkouttime']) ? $hotelBookDetail['checkouttime'] : '12:00';
            $hotelCheckinTime = isset($hotelBookDetail['checkintime']) ? $hotelBookDetail['checkintime'] : '14:00';
            $enddate = substr($orderRoomFound['enddate'],0,10). ' ' .$hotelCheckoutTime;
            // 订单已成过期的入住订单，无法再开门，所以也不能重发
            if (strtotime($enddate) <= time()) {
                throw new \Exception('403,506', 506);
            }

            $canPreGetCard = date('H') < substr($hotelCheckinTime, 0, 2) ? true : false;
            $canPreGetCardSubOrderIds = array();
            if ($canPreGetCard) {
                // 处理提前入住数据
                $canPreGetCardSubOrders = array();
                array_push($canPreGetCardSubOrders, array(
                    'roomId' => $orderRoomFound['roominfo_id'],
                    'startdate' => $orderRoomFound['startdate'],
                    'enddate' => $orderRoomFound['enddate'],
                    'orderRoomId' => $orderRoomId,
                ));
                $canPreGetCardIndex = $this->getCanPreGetCardIndex($hotelId, $canPreGetCardSubOrders);
                foreach ($canPreGetCardIndex as $indexValue) {
                    array_push($canPreGetCardSubOrderIds, $canPreGetCardSubOrders[$indexValue]['orderRoomId']);
                }
            }
            // 查看是否能提前获取房卡,以更新userRoom数据
            $checkInCanPreGetCard = $canPreGetCard && in_array($orderRoomFound['id'], $canPreGetCardSubOrderIds);
            $orderRoomFound['startTime'] = substr($orderRoomFound['startdate'], 0, 11) . ($checkInCanPreGetCard ? date('H:i:s') : $hotelCheckinTime);
            $orderRoomFound['endTime'] = substr($orderRoomFound['enddate'], 0, 11) . $hotelCheckoutTime;
        }
        
        

        

        // 查询已经生成的美住房卡ID，加密后的cardNo        
        $hotelEntityModel = D('HotelEntity');
        $hotelEntityItem = $hotelEntityModel->getInfo($hotelId);
        $communityNo = $hotelEntityItem['communityno'];
        Vendor('phpRPC.phprpc_client');
        $client = new \PHPRPC_Client(C('MANAGE_QRCLIENT_URL'));
        $client->setEncryptMode(3);
        $sendData = array(
            'flag' => 'uclbrt',
            'time' => time(),
            'communityNo' => $communityNo,
            'order' => $orderRoomFound
        );
        $clientData = $client->meizhuGetCard($sendData);
        if ($clientData['status'] == 102) 
        {            
            /**生成房卡（临时）**/            
            $makeData = array(
                'flag' => 'uclbrt',
                'communityNo' => $communityNo,
                'time' => time(),
                'type' => 0,
                'new' => array(
                    array(
                        'orderRoomId' => $orderRoomFound['id'],
                        'name' => $orderRoomFound['name'],
                        'areacode' => $orderRoomFound['areacode'],
                        'mobile' => $orderRoomFound['mobile'],
                        'roomName' => $orderRoomFound['roominfo_name'],
                        'startdate' => $orderRoomFound['startdate'],
                        'enddate' => $orderRoomFound['enddate'],
                        'startTime' => $orderRoomFound['startTime'],
                        'endTime' => $orderRoomFound['endTime'],
                    )
                ),
                'old' => array(),
            );
            
            $fileLog = new \Org\Util\FileLog();
            $fileLog->write(json_encode($orderRoomFound), 0, RUNTIME_PATH . "/Statistics/" . date('Y-m-d') . "_manualCreate.log");
            
            $makeResult = $client->meizhuMakeCard($makeData);
            $clientData = $client->meizhuGetCard($sendData);
            if ($clientData['status'] != 200) {
                throw new \Exception('403,508', 508);
            }            
            /**生成房卡结束**/
        }
        else if ($clientData['status'] != 200) 
        {
            throw new \Exception('403,508', 508);
        }

        $encodedCardNo = $clientData['data'];

        // 发送短信
        if ($orderRoomFound['areacode'] == '86') {
            $smsUtil = new \Org\Util\Sms();
            $smsResult = $smsUtil->sendNoLoginCardMessage($orderRoomFound['mobile'], $orderRoomFound['roominfo_name'], $orderRoomFound['startTime'], $orderRoomFound['endTime'], $encodedCardNo); 
        } else {
            $smsUtil = new \Org\Util\yunPian();
            $smsResult = $smsUtil->sendNoLoginCardMessage($orderRoomFound['areacode'], $orderRoomFound['mobile'], $orderRoomFound['roominfo_name'], $orderRoomFound['startTime'], $orderRoomFound['endTime'], $encodedCardNo);
        }
        
        $fileLogUtil = new \Org\Util\FileLog();
        $smsLogDetail = array(
            "areacode" => $orderRoomFound['areacode'],
            "mobile" => $orderRoomFound['mobile'],
            'hotelId' => $hotelId,
            'roomName' => $orderRoomFound['roominfo_name'],
            'startTime' => $orderRoomFound['startTime'],
            'endTime' => $orderRoomFound['endTime']
        );
        if ($smsResult == false) {
            //记录发送短信失败日志
            $fileLogUtil->write(json_encode($smsLogDetail), 1, RUNTIME_PATH . "/Statistics/Sms/" . date('Y-m-d') . "_error.log");
            throw new \Exception('403,151', 151);
        } else {
            $fileLogUtil->write(json_encode($smsLogDetail), 0, RUNTIME_PATH . "/Statistics/Sms/" . date('Y-m-d') . "_success.log");
            $this->redisUtil->hMSet($orderRoomFound['orderinfo_id'], array('times' => $sendTimes, 'update_time' => time()), strtotime(date('Y-m-d',strtotime('+1 day'))));
        }
        // 正常发送的话，需要返回这个是第几次发送
        return $sendTimes;
    }

    /**
     * 增加用户已打印次数
     * 方法会抛异常 \Exception
     * @modify trainyao 2016-08-23   创建
     * @param  mixin   $userRoomIds 用户房间userRoomId(s)
     * @return  boolean 执行结果
     */
    public function addPrintCount($userRoomIds) {
        $userRoomModel = D('UserRoom');
        $userRoomInfo = $userRoomModel->getInfo($userRoomIds);
        $userRoomInfo  = getArrayValueAsIndex($userRoomInfo, 'printcount', 'multi');

        if (!$this->getMultiTransMode()) {
            $userRoomModel->startTrans();
        }
        $commit = true;

        foreach ($userRoomInfo as $printCount => $userRooms) {
            $addResult = $userRoomModel->savePrintCount(array_column($userRooms, 'id'), ((int)$printCount + 1));
            if (empty($addResult)) {
                $commit = false;
                break;
            }
        }
        unset($userRooms);

        if ($commit) {
            if (!$this->getMultiTransMode()) {
                $userRoomModel->commit();
            }
            return true;
        } else {
            if (!$this->getMultiTransMode()) {
                $userRoomModel->rollback();
            }
            throw new \Exception('500,508', 508);
            return false;
        }
    }
    /**
     * 增加用户签发RF卡次数
     * @modify paddy 2017-6-2   创建
     * @param  mixin   $userRoomIds 用户房间userRoomId(s)
     * @return  boolean 执行结果
     */
    public function addRfCount($userRoomIds) {
        $userRoomModel = D('UserRoom');
        $userRoomInfo = $userRoomModel->getInfo($userRoomIds);
        $userRoomInfo  = getArrayValueAsIndex($userRoomInfo, 'rfcount', 'multi');
    
        if (!$this->getMultiTransMode()) {
            $userRoomModel->startTrans();
        }
        $commit = true;
    
        foreach ($userRoomInfo as $printCount => $userRooms) {
            $addResult = $userRoomModel->saveRfCount(array_column($userRooms, 'id'), ((int)$printCount + 1));
            if (empty($addResult)) {
                $commit = false;
                break;
            }
        }
        unset($userRooms);
    
        if ($commit) {
            if (!$this->getMultiTransMode()) {
                $userRoomModel->commit();
            }
            return true;
        } else {
            if (!$this->getMultiTransMode()) {
                $userRoomModel->rollback();
            }
            throw new \Exception('500,508', 508);
            return false;
        }
    }
    /**
     * 根据变化数据,修改订单统计表数据
     * @modify trainyao 2016-01-26       从后台服务迁移到订单逻辑,以防服务挂掉统计数据出错
     * @param  integer   $changeType            类型
     * @param  array   $oldOrderInfos       修改前信息数组 [{id(子订单ID)}, {}, ..]
     * @param  array   $newOrderInfos       修改后信息数组 [{status, startdate, checkoutdate, payment, night, hotelentity_id, roominfo_id, id(子订单ID)}, {}, ...]
     * @return mixin                    执行结果
     */
    protected function pushBackendTask($changeType, $oldOrderInfos, $newOrderInfos) {
        $operateTime = time();
        $fileLog = new \Org\Util\FileLog();
        switch ($changeType) {
            case $this->backendTaskType['ADD']:
                ob_start();
                echo "INSERT INTO `tb_order_room_report` (`hotelentity_id`, `date`, `roominfo_id`, `price`, `orderroom_id`, `status`) values ";
                $todayStartTime = strtotime(date('Y-m-d', $operateTime));
                $hasValue = false;
                foreach ($newOrderInfos as $newOrderInfo) {
                    // 如果修改子订单到过去,且修改订单是已入住或者已退房,才进行插入
                    if (strtotime($newOrderInfo['startdate']) < $todayStartTime && in_array($newOrderInfo['status'], array(ORDER_CHECKINED, ORDER_CHECKOUTED))) {
                        $needInsertDateTime = strtotime($newOrderInfo['checkoutdate']);

                        if ($needInsertDateTime >= $todayStartTime) {
                            $needInsertDateTime = $todayStartTime;
                        }

                        $dates = getDatesBetweenTime($newOrderInfo['startdate'], date('Y-m-d', $needInsertDateTime));
                        $dateLength = sizeof($dates);

                        $price = floatval($newOrderInfo['payment']) / intval($newOrderInfo['night']);
                        $price = number_format($price, 2, '.', '');

                        for ($i = 0; $i < $dateLength; $i++) {
                            $hasValue = true;
                            echo "('{$newOrderInfo['hotelentity_id']}', '{$dates[$i]}', '{$newOrderInfo['roominfo_id']}', '{$price}', '{$newOrderInfo['id']}', 1),";
                        }
                    }
                }
                $orderRoomReportSql = ob_get_contents();
                $orderRoomReportSql = chop($orderRoomReportSql, ',');
                ob_end_clean();

                if ($hasValue) {
                    $result = M('tb_order_room_report')->execute($orderRoomReportSql);
                    if (empty($result)) {
                        $fileLog->write('tb_order_room_report insert error', 1, RUNTIME_PATH . "/Statistics/Room/" . date('Y-m-d') . "_error.log");
                        return false;
                    }
                }

                break;
            case $this->backendTaskType['EDIT']:
                $orderRoomReportModal = M('tb_order_room_report');
                if (count($oldOrderInfos) !== 0) {
                    // 删除旧订单中,变化了的子订单的orderRoomReport条目
                    // (在oldOrderInfos里出现了的,在newOrderInfos也出现了的,为变化了的,根据id是否存在判断)
                    $needUpdateOrderRoomIds = array_column($newOrderInfos, 'id');
                    ob_start();
                    echo "delete from `tb_order_room_report` where `orderroom_id` in (";
                    foreach ($oldOrderInfos as $oldOrderInfo) {
                        if (in_array($oldOrderInfo['id'], $needUpdateOrderRoomIds)) {
                            echo $oldOrderInfo['id'], ',';
                        }
                    }
                    $deleteSql = ob_get_contents();
                    $deleteSql = chop($deleteSql, ',');
                    $deleteSql .= ')';
                    ob_end_clean();
                }

                $commit = true;
                if (!empty($deleteSql)) {
                    $result = $orderRoomReportModal->execute($deleteSql);
                    if ($result === false) {
                        $commit = false;
                        $fileLog->write('tb_order_room_report delete failed', 1, RUNTIME_PATH . "/Statistics/Room/" . date('Y-m-d') . "_error.log");
                    }
                }

                if ($commit && sizeof($newOrderInfos) !== 0) {
                    ob_start();
                    echo "INSERT INTO `tb_order_room_report` (`hotelentity_id`, `date`, `roominfo_id`, `price`, `orderroom_id`, `status`) values ";
                    $hasItemToInsert = false;
                    $todayStartTime = strtotime(date('Y-m-d', $operateTime));

                    foreach ($newOrderInfos as $newOrderInfo) {
                        if (strtotime($newOrderInfo['startdate']) < $todayStartTime) {
                            $needInsertDateTime = strtotime($newOrderInfo['checkoutdate']);
                            if ($needInsertDateTime >= $todayStartTime) {
                                $needInsertDateTime = $todayStartTime;
                            }
                            $dates = getDatesBetweenTime($newOrderInfo['startdate'], date('Y-m-d', $needInsertDateTime));
                            $dateLength = sizeof($dates);

                            $price = floatval($newOrderInfo['payment']) / intval($newOrderInfo['night']);
                            $price = number_format($price, 2, '.', '');

                            // 算出新插入的房间是已入住还是未入住
                            $checkinStatus = in_array($newOrderInfo['status'], array(ORDER_CHECKINED, ORDER_CHECKOUTED)) ? ENABLE : DISABLE;

                            for ($i = 0; $i < $dateLength; $i++) {
                                echo "('{$newOrderInfo['hotelentity_id']}', '{$dates[$i]}', '{$newOrderInfo['roominfo_id']}', '{$price}', '{$newOrderInfo['id']}', $checkinStatus),";
                                $hasItemToInsert = true;
                            }
                        }
                    }
                    // 存在需要删除,但不需要增加的情况,如将过去订单修改到今天或未来
                    // 所以没有条目需要插入,不执行sql,保证delete语句能commit
                    if ($hasItemToInsert) {
                        $orderRoomReportSql = ob_get_contents();
                        $orderRoomReportSql = chop($orderRoomReportSql, ',');
                        ob_end_clean();

                        $result = $orderRoomReportModal->execute($orderRoomReportSql);
                        if (empty($result)) {
                            $commit = false;
                            $fileLog->write('tb_order_room_report insert error', 1, RUNTIME_PATH . "/Statistics/Room/" . date('Y-m-d') . "_error.log");
                        }
                    } else {
                        ob_end_clean();
                    }
                }
                if (!$commit) {
                    $fileLog->write('tb_order_room_report rollback', 1, RUNTIME_PATH . "/Statistics/Room/" . date('Y-m-d') . "_error.log");
                    return false;
                }
                break;
            default:
                break;
        }
        $fileLog->write('data excute success!', 1, RUNTIME_PATH . "/Statistics/Room/" . date('Y-m-d') . "_success.log");
        return true;
    }

    /**
     * 移动端入住订单重发短信 返回短信数据 不经过第三方发送短信
     * @modify AmosZhong 2016-08-08  创建
     * @modify wenhui 2016-11-16 
     * @param  string or integer   $hotelId     客栈ID
     * @param  integer   $orderRoomId 子订单id,必须传一个id
     * @param  integer   $orderUserId 同住人ID,必须传一个id
     * @return boolean                是否在客栈内
     */
    public function resendMobileCheckInOrderSMS($hotelId, $orderRoomId, $orderUserId) {
        if (!is_numeric($orderRoomId)) {
            throw new \Exception('403,501', 501);
        }
        $orderRoomModel = D('OrderRoom');
        $orderRoomInfos = $orderRoomModel->getInfo($orderRoomId);
        if (empty($orderRoomInfos)) {
            throw new \Exception('403,501', 501);
        }

        // 查询
        $orderRoomFound = false;
        foreach ($orderRoomInfos as $orderRoomInfo) {
            if ($orderRoomInfo['hotelentity_id'] == $hotelId) {
                $orderRoomFound = $orderRoomInfo;
            }
        }
        // 找不到订单记录
        if (empty($orderRoomFound)) {
            throw new \Exception('403,501', 501);
        }

        // 获取同住人信息
        $orderUserModel = D('OrderUser');
        $orderUserInfo = $orderUserModel->getInfoByOrder($orderRoomFound['orderinfo_id']);
        if (!in_array($orderUserId, array_column($orderUserInfo, 'id'))) {
            throw new \Exception('403,202', 202);
            return false;
        }
        $orderUserInfo = getArrayValueAsIndex($orderUserInfo, 'id');
        if (empty($orderUserInfo[$orderUserId]['mobile'])) {
            throw new \Exception('403,504', 504);
            return false;
        }
        // 补充信息
        $orderRoomFound['name'] = $orderUserInfo[$orderUserId]['name'];
        $orderRoomFound['mobile'] = $orderUserInfo[$orderUserId]['mobile'];
        $orderRoomFound['identity'] = $orderUserInfo[$orderUserId]['identity'];


        // 订单不是入住状态
        if ($orderRoomFound['status'] != ORDER_CHECKINED) {
            throw new \Exception('403,505', 505);
        }

        $hotelLogic = A('Common/Hotel', 'Logic');
        $hotelCheckoutTime = $hotelLogic->getHotelBookingDetail($hotelId);
        $hotelCheckoutTime = isset($hotelCheckoutTime['checkouttime']) ? $hotelCheckoutTime['checkouttime'] : '12:00';
        $enddate = substr($orderRoomFound['enddate'],0,10). ' ' .$hotelCheckoutTime;
        // 订单已成过期的入住订单，无法再开门，所以也不能重发
        if (strtotime($enddate) <= time()) {
            throw new \Exception('403,506', 506);
        }

        // 查询已经生成的美住房卡ID，加密后的cardNo        
        $hotelEntityModel = D('HotelEntity');
        $hotelEntityItem = $hotelEntityModel->getInfo($hotelId);
        $communityNo = $hotelEntityItem['communityno'];
        Vendor('phpRPC.phprpc_client');
        $client = new \PHPRPC_Client(C('MANAGE_QRCLIENT_URL'));
        $client->setEncryptMode(3);
        $sendData = array(
            'flag' => 'uclbrt',
            'time' => time(),
            'communityNo' => $communityNo,
            'order' => $orderRoomFound
        );
        $clientData = $client->meizhuGetCard($sendData);
        if ($clientData['status'] != 200) {
            throw new \Exception('403,508', 508);
        }

        $encodedCardNo = $clientData['data'];

        // 获取客栈最迟退房时间
        $hotelLogic = A('Common/Hotel', 'Logic');
        $hotelBookDetail = $hotelLogic->getHotelBookingDetail($hotelId);
        $hotelCheckoutTime = isset($hotelBookDetail['checkouttime']) ? $hotelBookDetail['checkouttime'] : '12:00';
        $hotelCheckinTime = isset($hotelBookDetail['checkintime']) ? $hotelBookDetail['checkintime'] : '14:00';
        $canPreGetCard = date('H') < substr($hotelCheckinTime, 0, 2) ? true : false;

        $canPreGetCardSubOrderIds = array();
        if ($canPreGetCard) {
            // 处理提前入住数据
            $canPreGetCardSubOrders = array();
            array_push($canPreGetCardSubOrders, array(
                'roomId' => $orderRoomFound['roominfo_id'],
                'startdate' => $orderRoomFound['startdate'],
                'enddate' => $orderRoomFound['enddate'],
                'orderRoomId' => $orderRoomId,
            ));
            $canPreGetCardIndex = $this->getCanPreGetCardIndex($hotelId, $canPreGetCardSubOrders);
            foreach ($canPreGetCardIndex as $indexValue) {
                array_push($canPreGetCardSubOrderIds, $canPreGetCardSubOrders[$indexValue]['orderRoomId']);
            }
        }
        // 查看是否能提前获取房卡,以更新userRoom数据
        $checkInCanPreGetCard = $canPreGetCard && in_array($orderRoomFound['id'], $canPreGetCardSubOrderIds);
        $orderRoomFound['startdate'] = substr($orderRoomFound['startdate'], 0, 11) . ($checkInCanPreGetCard ? date('H:i:s') : $hotelCheckinTime);
        $orderRoomFound['enddate'] = substr($orderRoomFound['enddate'], 0, 11) . $hotelCheckoutTime;

        // 发送短信
        $smsUtil = new \Org\Util\Sms();
        $smsResult = $smsUtil->sendMobileNoLoginCardMessage($orderRoomFound['mobile'], $orderRoomFound['roominfo_name'], $orderRoomFound['startdate'], $orderRoomFound['enddate'], $encodedCardNo);

        if ($smsResult == false) {
            //记录发送短信失败日志
            throw new \Exception('403,151', 151);
        }

        // 正常发送的话，需要返回这个是第几次发送
        return $smsResult;
    }

    /**
     * 获取房间信息 需要返回二维数组
     * @modify wenhui 2016-12-01 创建
     * @param  integer   $roomId   房间id
     * @return array              房间信息
     */
    public function getRoomInfo($roomId) {
        $roomInfoModel = D('RoomInfo');
        $roomInfo = $roomInfoModel->getRoomInfo($roomId);
        if (empty($roomInfo)) {
            return array();
        }

        return $roomInfo;
    }

    /**
     * @param $orderDetails
     * @param $hotelId
     * @param $type 钟点房 =1 ，长租房 =2
     * @throws \Exception
     */
    private function checkRoomType($orderDetails, $hotelId, $type) {
        $roomArr = [];
        switch ($type) {
            case 1 :
                $hourRoomInfos = D('HourRoom')->getInfosByHotel($hotelId);
                $roomArr = array_column($hourRoomInfos, 'roominfo_id');
                break;
            case 2 :
                $longRoomInfos = D('LongRoom')->getInfosByHotel($hotelId);
                $roomArr = array_column($longRoomInfos, 'roominfo_id');
                break;
        }
        // 判断前端传来的房间ID是否都有权限
        if (!empty(array_diff(array_column($orderDetails, 'roomId'), $roomArr))) {
            throw new \Exception('403,301', 301);
        }
    }

    /**
     * @param 修改会员卡
     * @modify wenhui 2017-12-07 创建
     * @param $hotel 客栈id
     * @param $mobile 手机
     * @param $areaCode 区号
     * @param $receives 收款数据
     * @param $channel 操作渠道 0=美住网页 1=支美住app 2=微预定
     * @param $bookingUserId 微预定用户id
     * @return bool
     */
    private function modifyVipUserCard($hotel, $mobile, $areaCode, $receives, $channel = 0, $bookingUserId = 0) {
        $adminHotelModel = D('AdminHotel');
        $vipUserModel = D('VipUser');
        $vipUserCardModel = D('VipUserCard');
        $vipUserCardRecordModel = D('VipUserCardRecord');
        $vipInitModel = D('VipInit');

        $vipUserInfo = $vipUserModel->getInfoByMobile($hotel, $mobile, $areaCode);
        // 不是会员
        if (empty($vipUserInfo)) {
            return true;
        }

        $hotelLogic = A('Common/hotel', 'Logic');
        $hotelPayData = $hotelLogic->getHotelPay($hotel, false, 'zh_cn', true);
        $hotelPayData = getArrayValueAsIndex($hotelPayData, 'id');
        // 处理数据
        $price = 0;
        foreach ($receives as $key => $receive) {
            if ($hotelPayData[$receive['type']]['name'] == '会员卡') {
                $categoryArray = [PAY_CHANGE_RECEIPT];

                // 微预定 会员卡支持付押金
                if ($channel == ORDER_CHANGE_BOOK_WEB) {
                    $categoryArray = [PAY_CHANGE_RECEIPT,PAY_CHANGE_DEPOSIT];
                }

                if (in_array($receive['category'], $categoryArray)) {
                    $price += $receive['value'];
                    $payType = $receive['type'];
                } else {
                    // 会员卡暂不支持押金(其他)
                    throw new \Exception('403,711', 711);
                    return false;
                }
            }
        }
        // 没有会员卡支付 则不修改会员卡
        if (!isset($payType)) {
            return true;
        }

        // 获取原来的卡金额
        $vipUserCardInfo = $vipUserCardModel->getInfoByVipUserId($vipUserInfo['id']);
        $cardPrice = $vipUserCardInfo['price'] - $price;
        if ($cardPrice < 0) {
            // 卡余额不足
            throw new \Exception('403,710', 710);
            return false;
        }

        $hotelCreator = $adminHotelModel->getHotelCreator($hotel);
        // 会员分享方式
        $vipInitInfo = $vipInitModel->getInfoByAdmin($hotelCreator['adminlogin_id']);
        if (empty($vipInitModel)) {
            return true;
        }

        $adminId = getUserId();
        $commit = true;
        $addRecordData = array();
        if($vipInitInfo['share'] == '1'){
            $adminHotelInfos = $adminHotelModel->getInfosByAdmin($hotelCreator['adminlogin_id']);
            $hotelIds = array_column($adminHotelInfos, 'hotelentity_id');
            $vipUserInfo = $vipUserModel->getInfosByMobile($hotelIds, $mobile, $areaCode);

            // 获取支付方式
            $hotelLogic = A('Common/Hotel', 'Logic');
            $hotelpayInfo = $hotelLogic->getHotelPay($hotelIds, true, 'zh_cn', true);
            $hotelpayInfo = getArrayValueAsIndex($hotelpayInfo, 'hotelentity_id');
            foreach ($hotelpayInfo as $key => &$hotelpayItem) {
                $hotelpayItem = getArrayValueAsIndex($hotelpayItem, 'id');
            }
            unset($hotelpayItem);

            foreach ($vipUserInfo as $key => $vipUserItem) {
                $saveResult = $vipUserCardModel->saveVipUserCardInfo($vipUserItem['id'], $cardPrice);
                if ($saveResult === false) {
                    $commit = false;
                    break;
                }

                // 获取支付方式id
                foreach ($hotelpayInfo[$vipUserItem['hotelentity_id']] as $key => $hotelpayItem) {
                    if ($hotelpayInfo[$hotel][$payType]['name'] == $hotelpayItem['name']) {
                        $hotelPayType = $hotelpayItem['id'];
                    }
                }
                unset($hotelpayItem);

                // 记录数据
                array_push($addRecordData, array(
                    'hotelentity_id' => $hotel, // 当前操作客栈
                    'vipuser_id' => $vipUserItem['id'],
                    'price' => $cardPrice,
                    'change_price' => $price,
                    'type' => 2,
                    'pay_type' => isset($hotelPayType) ? $hotelPayType : '0',
                    'channel' => $channel,
                    'remark' => '',
                    'bk_user_id' => $bookingUserId,
                    'creator' => $adminId,
                    'operator' => $adminId,
                ));
            }
            unset($vipUserItem);
        } else {
            $saveResult = $vipUserCardModel->saveVipUserCardInfo($vipUserInfo['id'], $cardPrice);
            if ($saveResult === false) {
                $commit = false;
            }
            // 记录数据
            array_push($addRecordData, array(
                'hotelentity_id' => $hotel, // 当前操作客栈
                'vipuser_id' => $vipUserInfo['id'],
                'price' => $cardPrice,
                'change_price' => $price,
                'type' => 2,
                'pay_type' => $payType,
                'channel' => $channel,
                'remark' => '',
                'bk_user_id' => $bookingUserId,
                'creator' => $adminId,
                'operator' => $adminId,
            ));
        }

        if ($commit && !empty($addRecordData)) {
            // 添加记录
            $addResult = $vipUserCardRecordModel->addAll($addRecordData);
            if ($addResult == false) {
                $commit = false;
            }
        }

        if ($commit) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @param 支付记录 收款详情
     * @modify wenhui 2017-12-07 创建
     * @param $orderId 订单id
     */
    public function getOrderPayRecordSum ($orderId) {
        // 订单金额加上 新的其他消费已收金额
        $orderRecordModel = D('OrderRecord');
        $orderRecordInfos = $orderRecordModel->getInfoByOrder($orderId);
        $orderRecordIds = array_column($orderRecordInfos, 'id'); 
        $payHistoryInfo = $this->getPayHistoryData($hotelId, $orderRecordIds, true);
        
        // 计算其他消费 已收
        $otherReceivePrice = 0;
        if (!empty($payHistoryInfo)) {
            foreach ($payHistoryInfo as $key => $payHistoryItem) {
                if (!in_array($payHistoryItem['type'], [0,1,2,3])) {
                    if ($payHistoryItem['hotelpay_id'] != 0) {
                        // 他消费已收金额
                        $otherReceivePrice += $payHistoryItem['pay'];
                    }
                }
            }
            unset($payHistoryItem);
        }

        return array('otherReceivePrice' => $otherReceivePrice);
    }

    /**
     * 添加订单房间查房数据
     * @modify wenhui 2018-02-26 创建
     * @param $hotelId
     */
    public function addOrderRoomCheck($hotelId, $orderId, $subOrderIds) {
        try {
            $orderInfo = $this->getOrderInfo($hotelId, $orderId, true, false);
        } catch (\Exception $e) {
            throw $e;
            return false;
        }

        $orderRoomInfo = $orderInfo[0]['rooms'];
        $enableCheckRoom = $this->hotelCheckRoomSwitch($hotelId);
        $commit = true;
        if ($enableCheckRoom == false) {
            $commit = false;
        }

        if ($commit) {
            // 添加查房记录|查房操作记录 并向app发起查房服务
            $addResult = $this->addCheckRoom($hotelId, $orderId, $subOrderIds, $orderRoomInfo);
            if ($addResult == false) {
                $commit = false;
            }
            if ($commit) {
                $upshResult = $this->pushCheckRoomTask($hotelId, $subOrderIds, 'web');
                /*if ($upshResult == false) {
                    $commit = false;
                }*/
            }
        }

        if (!$commit) {
            throw new \Exception('500,512', 512);
            return false;
        }

        return $addResult;
    }

    /**
     * 检查客栈查房开关
     * @modify wenhui 2018-02-26 创建
     * @param $hotelId
     */
    public function hotelCheckRoomSwitch($hotelId) {
        $hotelEntityModel = D('HotelEntity');
        $hotelInfo = $hotelEntityModel->getInfo($hotelId);

        $enable = $hotelInfo['roomward'] == ENABLE ? true : false;
        return $enable;
    }

    /**
     * 添加查房记录 | 查房操作记录
     * @modify wenhui 2018-02-26
     * @param integer $hotelId 客栈id
     * @param integer $orderId 订单id
     * @param array $subOrderIds 子订单id [12,34,34...]
     * @param array $orderRoomInfo 订单房间信息数组 [['id' => 1, 'name' => 'xx', 'roominfo_name' => '401G', 'roominfo_id' => 123], [['id' => 2, 'roominfo_name' => '402G', ...]]]
     */
    private function addCheckRoom($hotelId, $orderId, $subOrderIds, $orderRoomInfo) {
        $hotelRoomCheckModel = D('HotelRoomCheck');
        $hotelEntityModel = D('HotelEntity');
        $hotelRoomAuthorityModel = D('HotelRoomAuthority');
        $adminAuthorityModel = D('AdminAuthority');
        $orderRecordModel = D('OrderRecord');


        $orderRoomInfo = getArrayValueAsIndex($orderRoomInfo, 'id');
        $userId = getUserId();
        $addInfos = array();
        foreach ($subOrderIds as $key => $subOrderId) {
            $name = isset($orderRoomInfo[$subOrderId]) ? $orderRoomInfo[$subOrderId]['name'] : '';
            $roomname = isset($orderRoomInfo[$subOrderId]) ? $orderRoomInfo[$subOrderId]['roominfo_name'] : '';
            $addInfos[] = array(
                'adminlogin_id_send' => $userId,
                'adminlogin_id_check' => 0,
                'hotelentity_id' => $hotelId,
                'orderinfo_id' => $orderId,
                'orderroom_id' => $subOrderId,
                'name' => $name,
                'roomname' => $roomname,
                'remark' => '',
                'type' => 0,
                'isdelete' => 0,
                'creator' => 0,
                'operator' => 0,
            );
        }
        unset($subOrderId);

        $hotelRoomCheckModel->startTrans();
        $commit = true;
        $addResult = $hotelRoomCheckModel->addAllInfo($addInfos);
        if ($addResult == false) {
            $commit = false;
        }

        // 添加redis
        if ($commit) {
            // 构造推送消息
            $hoteldata = $hotelEntityModel->getInfo($hotelId);
            $alert = [
                'zh_cn' => ['查房'],
                'en_us' => ['Check room']
            ];
            if ($hoteldata['universaltime_id'] == 5) {
                $alertNews = $alert['zh_cn'];
            } else {
                $alertNews = $alert['en_us'];
            }

            $noticeString =  '[' . $alertNews[0] . ']' . $hoteldata['name'] . '：';
            // 根据hotelId 获取超管userId
            $adminHotelModel = D('AdminHotel');
            $adminInfo = $adminHotelModel->getHotelCreator($hotelId);
            $adminloginId = $adminInfo['adminlogin_id'];
            $adminIdAuthoruty = array();
            foreach ($subOrderIds as $key => $subOrderId) {
                $adminIdAuthoruty[] = array(
                    'adminlogin_id' => $adminloginId,
                    'subOrderId' => $subOrderId,
                    'notice' => $noticeString . $orderRoomInfo[$subOrderId]['roominfo_name'] . '。',
                );
            }
            unset($subOrderId);

            // 获取对该房间有权限的管理员id
            foreach ($orderRoomInfo as $key => $orderRoom) {
                $hotelRoomAuthorityInfo = $hotelRoomAuthorityModel->getInfoByHotelRoom($hotelId, $orderRoom['roominfo_id']);
                if (!empty($hotelRoomAuthorityInfo)) {
                    foreach ($hotelRoomAuthorityInfo as $key => $roomAuthority) {
                        // 校验有查房权限
                        $authorityResult = $adminAuthorityModel->getInfoByAdminHotelAuthority($roomAuthority['adminlogin_id'], $hotelId, 27);
                        if (!empty($authorityResult)) {
                            $adminIdAurhorutyItem = array(
                                'adminlogin_id' => $roomAuthority['adminlogin_id'],
                                'subOrderId' => $orderRoom['id'],
                                'notice' => $noticeString . $orderRoom['roominfo_name'] . '。',
                            );
                            array_push($adminIdAuthoruty, $adminIdAurhorutyItem);
                        }
                    }
                    unset($roomAuthority);
                }
            }
            unset($orderRoom);

            $adminIdAuthoruty = getArrayValueAsIndex($adminIdAuthoruty, 'subOrderId', true);

            $redisUtil = new \Org\Util\RedisHelper(null, null, 'meizhu');
            $redisUtil->db(C('REDIS_ORDER_PUSH_DB'))->table('checkRoomPush');
            foreach ($subOrderIds as $key => $subOrderId) {
                $subOrderIdInfo = json_encode($adminIdAuthoruty[$subOrderId]);
                $redisResult = $redisUtil->hMSet($hotelId . '_' . $subOrderId, [$subOrderIdInfo]);
                if ($redisResult == false) {
                    $commit = false;
                    break;
                }
            }
            unset($subOrderId);
        }

        if ($commit) {
            // 生成单次操作记录id
            $orderRecordId = $orderRecordModel->addInfo($orderId, 0, null, null, null, null, null, null, 1);
            if (empty($orderRecordId)) {
                $commit = false;
            }

            if ($commit) {
                $orderCheckRoomRecords = array(
                    array(
                        'orderrecord_id' => $orderRecordId,
                        'checktype' => 1,
                        'hotelroomcost_id' => '',
                        'remark' => '',
                        'checktype_before' => '',
                        'hotelroomcost_id_before' => '',
                        'remark_before' => '',
                        'type' => 1,
                    ),
                );

                $checkoutResult = $this->changeSubOrder($hotelId, $orderId, $orderRecordId, null, null, null, null, $orderCheckRoomRecords); 
                if (!$checkoutResult) {
                    $commit = false;
                }
            }
        }

        if ($commit) {
            $hotelRoomCheckModel->commit();
            return true;
        } else {
            $hotelRoomCheckModel->rollback();
            return false;
        }
    }

    /**
     * 发送请求到后台进行推送消息，提醒客户端
     * @modify wenhui 2018-02-26
     * @param integer $hotelId 客栈id
     * @param array $subOrderIds 子订单id
     * @param string $fromPush  推送来源
     * @param integer $sendAdminId  发起查房用户ID
     * @return bool
     */
    public function pushCheckRoomTask($hotelId, $subOrderIds, $fromPush, $sendAdminId = null) {
        $fileLog = new \Org\Util\FileLog();
        // 定义数据类型格式
        $data = array(
            'hotel' => $hotelId,
            'subOrderIds' => json_encode($subOrderIds),
            'from' => $fromPush,
            'sendAdminId' => $sendAdminId,
        );

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, 'http://' . C('SOCKET_SERVER_CHECKROOM_IP') . ':' . C('SOCKET_SERVER_CHECKROOM_PORT'));
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $result = curl_exec($ch);

        if ($result != 'success') {
            $fileLog->write('push failed!' . json_encode($data), 0, RUNTIME_PATH . "/Logs/Home/" . date('Y-m-d') . "_roomcheck.log");
            return false;
        }
        return true;
    }
}
